package com.bbcare.followup.plat.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.bbcare.comm.*;
import com.bbcare.comm.enumeration.HospitalTypeEnum;
import com.bbcare.comm.enumeration.PatientHospitalStatusEnum;
import com.bbcare.department.plat.entity.Contact;
import com.bbcare.department.plat.entity.DepartmentBasic;
import com.bbcare.department.plat.entity.Doctor;
import com.bbcare.department.plat.entity.RandOutPatientSchedule;
import com.bbcare.department.plat.service.IBsSmsTemplateService;
import com.bbcare.department.plat.store.ibatis.IContactDao;
import com.bbcare.department.plat.store.ibatis.IDeparmentBasicDao;
import com.bbcare.department.plat.store.ibatis.IDoctorDao;
import com.bbcare.department.plat.store.ibatis.IOutPatientScheduleDao;
import com.bbcare.followup.plat.dto.bo.PatientListBO;
import com.bbcare.followup.plat.dto.request.PatientPageReqDTO;
import com.bbcare.followup.plat.dto.request.PatientUpdateStatusReqDTO;
import com.bbcare.followup.plat.entity.*;
import com.bbcare.followup.plat.service.*;
import com.bbcare.followup.plat.store.ibatis.*;
import com.bbcare.followup.plat.task.QuestionsComparator;
import com.bbcare.followup.plat.task.TaskComparator;
import com.bbcare.followup.plat.vo.FuClosecaseRecordVo;
import com.bbcare.plat.redis.service.IPatientQueueRedis;
import com.bbcare.plat.support.service.IBizInterAsClient;
import com.bbcare.treat.plat.entity.PtArchiveTask;
import com.bbcare.treat.plat.entity.PtTrTask;
import com.bbcare.treat.plat.service.impl.PatientTreatService;
import com.bbcare.treat.plat.store.ibatis.IPtArchiveTaskDAO;
import com.bbcare.treat.plat.store.ibatis.IPtTrTaskDAO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @name: 患者信息服务类实现
 * @author: DemonLee
 * @createTime: 2017.4.11
 * @description: 患者相关操作等
 * @modify:
 */
@Service
public class PatientService implements IPatientService {
    private final Log logger = LogFactory.getLog(PatientService.class);

    @Autowired
    private IPatientDAO patientDao;

    @Autowired
    private IFollowQueueDAO queueDao;

    @Autowired
    private IPtUserInfoExtDAO ptUserInfoExtDAO;

    @Autowired
    private IPatientTaskContentDAO patientTaskContentDAO;

    @Autowired
    private IPatientQueueSchemeDAO patientQueueSchemeDao;

    @Autowired
    private IFdHospitalEmailConfigDAO fdHospitalEmailConfigDAO;

    @Autowired
    private IFollowTaskDAO followTaskDao;

    @Autowired
    private IFollowTaskContentDAO followTaskContDao;

    @Autowired
    private IContentTemplDAO contentTemplDao;

    @Autowired
    private IPatientTaskDAO patientTaskDao;

    @Autowired
    private IPtArchiveTaskDAO ptArchiveTaskDao;

    @Autowired
    private IPtTrTaskDAO ptTrTaskDao;

    @Autowired
    private IPatientTaskContentDAO patientTaskConDao;

    @Autowired
    private IPatientQueueRedis ptQueueRedis;

    @Autowired
    private IPatientInfoHisService patientInfoHisService;

    @Autowired
    private IBsSmsTemplateService bsSmsTemplateService;

    @Autowired
    private IDeparmentBasicDao deparmentBasicDao;

    @Autowired
    private IPatientOperationRecordDAO patientOperationRecordDao;

    @Autowired
    private IFollowSchemeDAO followSchemeDao;

    @Autowired
    private IPatientAccountDAO ptAccountDao;

    @Autowired
    private IPatientExtendDAO ptExtendDao;

    @Autowired
    private IFollowQueueService followQueueService;

    @Autowired
    public IConfCacheDAO confCacheDao;

    @Autowired
    private IOutPatientScheduleDao outPatientScheduleDao;

    @Autowired
    private IContactDao deptContactDao;

    @Autowired
    private AppPatientAotuService AppPatientAotuService;

    @Autowired
    private IBizInterAsClient bizInterClient;

    @Autowired
    private IFuTaskRuleDao fuTaskRuleDao;

    @Autowired
    private IPtExcpRdDao ptExcpDao;

    @Autowired
    private FamilyReportService familyReportService;

    @Autowired
    private IPtQueueExtendDao ptQueueExtendDao;

    @Autowired
    private IConfCacheDAO IConfCacheDAO;

    @Autowired
    private PatientTreatService patientTreatService;

    @Autowired
    private IFollowEvaluationDAO followEvaluationDao;

    @Autowired
    private IExtendService extendService;

    @Autowired
    private FuClosecaseRecordDao fuClosecaseRecordDao;

    @Resource(name = "jedisPool")
    private JedisPool jedisPool;

    @Autowired
    private IScanDataSynchService scanDataSynchService;

    @Autowired
    private IDoctorDao doctorDao;

    @Autowired
    private FuReferralRecordDao fuReferralRecordDao;

    @Autowired
    private IFollowQueueAuthorityDAO followQueueAuthorityDAO;

    public static String emailHtml =
            "日期:  {日期} \n" +
                    "住院号:  {住院号} \n" +
                    "房间床号:  {房间床号} \n" +
                    "姓名:  {姓名} \n" +
                    "性别:  {性别} \n" +
                    "孕周:  {孕周} \n" +
                    "转运体重:  {转运体重} \n" +
                    "产院:  {产院} \n" +
                    "转入诊断:  {转入诊断} \n" +
                    "转出诊断:  {转出诊断} \n" +
                    "转出日期:  {转出日期} \n" +
                    "转归:  {转归}";

    // 患者随访建档信息
    public List<Object> listPtFuArchInfo(Map<String, Object> paramMap) throws Exception {
        List<Object> retList = new ArrayList<Object>();
        String queueId = (String) paramMap.get("queueId");
        String ptSchemeIdOri = (String) paramMap.get("ptSchemeId");
        // 无队列id
        if (StringUtils.isEmpty(queueId)) {
            paramMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
            List<Map<String, Object>> ptList = patientDao.selectPtSchemeAndPatientByPhoneAndQueueId(paramMap);
            if (!CollectionUtils.isEmpty(ptList) && StringUtils.isNotBlank(ptSchemeIdOri)) {
                int size = ptList.size();
                for (int k = 0; k < size; k++) {
                    Map<String, Object> ptMap = new HashMap<String, Object>();
                    // 患者基本信息
                    ptMap = ptList.get(k);

                    // 患者扩展信息
                    Map<String, Object> outExtMap = new HashMap<String, Object>();
                    /*
                     * 后续再完善 Map<String, Object> ptExtMap = new HashMap<String,
                     * Object>(); ptExtMap.put("userId", ptMap.get("id"));
                     * ptExtMap.put("queueId", queueId); List<PtUserextendInfo>
                     * ptextList = ptExtendDao.selectPtExtendInfo(ptExtMap); if
                     * (null != ptextList && 0 != ptextList.size()) { int
                     * iextNum = ptextList.size(); int kk = 0; for (kk = 0; kk <
                     * iextNum; kk++) { PtUserextendInfo pextVo =
                     * ptextList.get(kk); outExtMap.put(pextVo.getParamName(),
                     * pextVo.getParamValue()); } }
                     */
                    ptMap.put("extendInfo", outExtMap);

                    // 患者建档问卷答案信息
                    String ptSchemeId = (String) ptMap.get("ptSchemeId");
                    Map<String, Object> taskMap = new HashMap<String, Object>();
                    taskMap.put("seqNo", Constants.TASK_SEQ_FOR_INIT);
                    taskMap.put("ptSchemeId", ptSchemeId);
                    taskMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
                    List<PatientTask> taskList = patientTaskDao.select(taskMap);
                    if (!CollectionUtils.isEmpty(taskList)) {
                        PatientTask ptVo = taskList.get(0);
                        Map<String, Object> cntMap = new HashMap<String, Object>();
                        cntMap.put("taskId", ptVo.getId());
                        List<PatientContentData> ptTaskConList = patientTaskConDao.selectContentDataByTaskId(cntMap);
                        HashMap<String, Object> questionMap = new HashMap<String, Object>();
                        if (!CollectionUtils.isEmpty(ptTaskConList)) {
                            int tt = 0;
                            for (; tt < ptTaskConList.size(); tt++) {
                                PatientContentData pcdVo = ptTaskConList.get(tt);
                                questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                            }
                        }
                        ptMap.put("values", questionMap);
                    }

                    retList.add(ptMap);
                }
            } else {
                retList = ToolUtils.typeCast(ptList);
            }
        } else {
            // 有队列id，查询患者基本信息和建档基本资料
            paramMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
            List<Map<String, Object>> ptList = patientDao.selectPtSchemeAndPatientByPhoneAndQueueId(paramMap);
            if (!CollectionUtils.isEmpty(ptList) && StringUtils.isNotBlank(ptSchemeIdOri)) {
                int size = ptList.size();
                for (int k = 0; k < size; k++) {
                    Map<String, Object> ptMap = new HashMap<String, Object>();
                    // 患者基本信息
                    ptMap = ptList.get(k);

                    // 患者扩展信息
                    Map<String, Object> outExtMap = new HashMap<String, Object>();
                    Map<String, Object> ptExtMap = new HashMap<String, Object>();
                    ptExtMap.put("userId", ptMap.get("id"));
                    ptExtMap.put("queueId", queueId);
                    List<PtUserextendInfo> ptextList = ptExtendDao.selectPtExtendInfo(ptExtMap);
                    if (null != ptextList && 0 != ptextList.size()) {
                        int iextNum = ptextList.size();
                        int kk = 0;
                        for (kk = 0; kk < iextNum; kk++) {
                            PtUserextendInfo pextVo = ptextList.get(kk);
                            outExtMap.put(pextVo.getParamName(), pextVo.getParamValue());
                        }
                    }
                    ptMap.put("extendInfo", outExtMap);

                    // 患者建档问卷答案信息
                    String ptSchemeId = (String) ptMap.get("ptSchemeId");
                    Map<String, Object> taskMap = new HashMap<String, Object>();
                    taskMap.put("seqNo", Constants.TASK_SEQ_FOR_INIT);
                    taskMap.put("ptSchemeId", ptSchemeId);
                    taskMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
                    List<PatientTask> taskList = patientTaskDao.select(taskMap);
                    if (!CollectionUtils.isEmpty(taskList)) {
                        PatientTask ptVo = taskList.get(0);
                        Map<String, Object> cntMap = new HashMap<String, Object>();
                        cntMap.put("taskId", ptVo.getId());
                        List<PatientContentData> ptTaskConList = patientTaskConDao.selectContentDataByTaskId(cntMap);
                        HashMap<String, Object> questionMap = new HashMap<String, Object>();
                        if (!CollectionUtils.isEmpty(ptTaskConList)) {
                            int tt = 0;
                            for (; tt < ptTaskConList.size(); tt++) {
                                PatientContentData pcdVo = ptTaskConList.get(tt);
                                questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                            }
                        }
                        ptMap.put("values", questionMap);
                    }

                    retList.add(ptMap);
                }
            } else {
                retList = ToolUtils.typeCast(ptList);
            }
        }
        return retList;
    }

    // 患者诊疗建档信息（后续通用建档信息）
    public List<Object> listPtTrArchInfo(Map<String, Object> paramMap) throws Exception {
        List<Object> retList = new ArrayList<Object>();
        String queueId = (String) paramMap.get("queueId");
        boolean isQueueId = true;
        if (StringUtils.isBlank(queueId)) {
            isQueueId = false;
        }
        // 入参中是否传了ptSchemeId
        String ptSchemeIdOri = (String) paramMap.get("ptSchemeId");
        // String oriQueueId = (String) paramMap.get("oriQueueId");//
        // 原始队列id(处理同一租户不同队列的情况)

        paramMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
        List<Map<String, Object>> ptList = patientDao.listPtArchInfoByCondition(paramMap);
        if (!CollectionUtils.isEmpty(ptList) && StringUtils.isNotBlank(ptSchemeIdOri)) {
            int size = ptList.size();
            String ptSchemeId = "";
            String ptTaskId = "";
            String userName = "";
            String userId = "";
            int dealTime = Integer.parseInt(DateUtil.getHm());// 15:30-->1530
            String currDate = DateUtil.getCurrDate();
            Map<String, Object> archMapOut = new HashMap<String, Object>();
            Map<String, Object> archMapIn = new HashMap<String, Object>();
            Map<String, Object> redisMap = new HashMap<String, Object>();

            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.select(Constants.REDIS_DB_INDEX_PATIENT);
                for (int k = 0; k < size; k++) {
                    Map<String, Object> ptMap = new HashMap<String, Object>();
                    archMapIn.clear();

                    // 患者基本信息
                    ptMap = ptList.get(k);
                    if (false == isQueueId) {
                        queueId = (String) ptMap.get("queueId");
                    }
                    userName = (String) ptMap.get("userName");
                    userId = (String) ptMap.get("id");
                    ptSchemeId = (String) ptMap.get("ptSchemeId");
                    ptTaskId = (String) ptMap.get("archiveTaskId");
                    archMapIn.put("ptSchemeId", ptSchemeId);
                    archMapIn.put("queueId", queueId);
                    archMapIn.put("ptTaskId", ptTaskId);
                    archMapIn.put("userId", userId);
                    // archMapIn.put("oriQueueId", oriQueueId);

                    archMapOut.clear();
                    archMapOut = patientTreatService.getPtArchInfo(archMapIn);
                    ptMap.put("schemeList", archMapOut.get("schemeList"));
                    ptMap.put("extendInfo", archMapOut.get("extendInfo"));
                    ptMap.put("values", archMapOut.get("values"));

                    // 查询记录入redis,userId※ptSchemeId※姓名
                    // if (StringUtils.isNotBlank(oriQueueId) &&
                    // oriQueueId.equals(queueId)) {
                    redisMap.clear();
                    redisMap.put("queueId", queueId);
                    redisMap.put("dealDate", currDate);
                    redisMap.put("userId", userId);
                    redisMap.put("ptSchemeId", ptSchemeId);
                    redisMap.put("userName", userName);
                    redisMap.put("dealTime", dealTime);
                    ptQueueRedis.saveOutPatientRedisforQueue(redisMap, jedis);
                    // }

                    retList.add(ptMap);
                }
            } catch (JedisConnectionException jex) {
                logger.error("redis连接异常..." + jex.getMessage());
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
            } finally {
                ToolUtils.closeRedis(jedis);
            }
        } else {
            retList = ToolUtils.typeCast(ptList);
        }

        return retList;
    }

    // 通过服务号码查询患者信息
    public List<Object> getPatientByPhoneNo(Map<String, Object> argMap) throws Exception {
        Map<String, Object> paramMap = new HashMap<String, Object>(argMap);
        List<Object> retList = new ArrayList<Object>();
        Integer schemeBusiType = (Integer) paramMap.get("schemeBusiType");
        if (null == schemeBusiType) {
            schemeBusiType = Constants.SCHEME_BUSI_TYPE_0;
        }
        // String queueId = (String) paramMap.get("queueId");
        // String ptSchemeIdOri = (String) paramMap.get("ptSchemeId");

        // 只查询基本信息
        String qryType = (String) paramMap.get("qryType");
        if (!StringUtils.isEmpty(qryType) && Constants.QRY_BASIC_USER_INFO_TYPE.equals(qryType)) {
            List<Map<String, Object>> ptList = patientDao.selectPtSchemeAndPatientByPhoneAndQueueId(paramMap);
            if (!CollectionUtils.isEmpty(ptList)) {
                Map<String, Object> ptMap = ptList.get(0);
                ptMap.put("userId", ptMap.get("id"));
                retList.add(ptMap);
            }
            return retList;
        }

        if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType) {
            // 随访
            retList = this.listPtFuArchInfo(paramMap);
        } else if (Constants.SCHEME_BUSI_TYPE_1 == schemeBusiType) {
            // 诊疗
            retList = this.listPtTrArchInfo(paramMap);
            // if (CollectionUtils.isEmpty(retList) &&
            // StringUtils.isNotBlank(queueId)
            // && StringUtils.isBlank(ptSchemeIdOri)) {
            // 查询当前租户非当前队列下的患者
            // paramMap.remove("queueId");
            // retList = this.listPtTrArchInfo(paramMap);
            // }
        } else {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEME_BUSITYPE_INCOMPATIBLE,
                    "暂不支持该方案业务类型: [" + schemeBusiType + "]！"));
        }
        return retList;
    }

    // 患者信息List实现
    public List<Patient> getPatientList(Map<String, Object> paramMap) throws Exception {
        return patientDao.select(paramMap);
    }

    /**
     * 患者队列任务实例化
     */
    public Map<String, Object> dealPtTaskIns(Map<String, Object> paramIn) throws Exception {
        logger.warn("---begin dealPtTaskIns---");
        Map<String, Object> servParamMap = new HashMap<String, Object>(paramIn);
        Map<String, Object> retOut = new HashMap<String, Object>();

        Patient pt = (Patient) servParamMap.get("patient");
        String queueId = (String) servParamMap.get("queueId");
        String updateTime = (String) servParamMap.get("updateTime");
        String authorId = (String) servParamMap.get("authorId");
        String updateAccept = (String) servParamMap.get("updateAccept");
        String authorName = (String) servParamMap.get("authorName");
        String opType = (String) servParamMap.get("opType");
        String userId = (String) servParamMap.get("userId");
        String ptQueueSchemeId = (String) servParamMap.get("ptQueueSchemeId");
        String schemeVersionId = (String) servParamMap.get("schemeVersionId");
        String taskId_0 = "";
        Map<String, Object> quesMap = ToolUtils.typeCast(servParamMap.get("contentData"));
        if (StringUtils.isEmpty(pt.getId())) {
            pt.setId(userId);
        }
        String tenantId = (String) servParamMap.get("tenantId");

        // 查询当前队列对应方案门诊任务
        HashMap<String, Object> taskQueryParam = new HashMap<String, Object>();
        taskQueryParam.put("schemeVersionid", schemeVersionId);
        taskQueryParam.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 0：门诊随访
        taskQueryParam.put("seqNo", Constants.TASK_SEQ_FOR_INIT);
        List<FollowTask> taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
        if (null == taskList || 0 == taskList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASK_NOT_EXIST, "当前方案对应任务列表为空！"));
        }
        taskQueryParam.remove("seqNo");

        // 实例化方案下任务信息给具体患者
        List<PatientTask> ptTaskList = new ArrayList<PatientTask>();
        List<PatientTaskContent> ptTaskContentList = new ArrayList<PatientTaskContent>();
        // List<String> taskIdList = new ArrayList<String>();
        FollowTask ft = new FollowTask();
        int iPrenDay = pt.getPregnancyDay();
        String birthDay = pt.getBirthday();
        String currDay = DateUtil.getCurrDate();
        Map<String, Object> executeMapIn = new HashMap<String, Object>();
        executeMapIn.put("currDay", currDay);
        executeMapIn.put("prenDay", iPrenDay);
        executeMapIn.put("birthDay", birthDay);
        if (!StringUtils.isEmpty(birthDay)) {// 微信产妇建档 可能没有生日选项
            executeMapIn.put("ageDay", ToolUtils.getBirthAgeDay(birthDay));
        }
        // 出院日期，暂无，先写上
        Map<String, Object> contentMap = (JSONObject) servParamMap.get("contentData");
        //executeMapIn.put("outHospitalDay", servParamMap.get("outHospitalDay"));
        if (contentMap!=null){
            executeMapIn.put("outHospitalDay", contentMap.get("outHospitalDay"));
        }
        // 初检孕周及末次月经日期（孕产妇随访）
        executeMapIn.put("firstChkPregWeek", servParamMap.get("firstChkPregWeek"));
        executeMapIn.put("lastMenstruationDate", servParamMap.get("lastMenstruationDate"));
        executeMapIn.put("deliveryDate", servParamMap.get("deliveryDate"));
        executeMapIn.put("inputContData", quesMap);
        int suffWinDay = 0;// 后窗口期
        int iWinDay = 0;// 前窗口期
        String endTime = "";
        String nextTaskId = "";
        String currTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
        int lostNum = 0;// 门诊随访失访任务数
        int onlineLostNum = 0;// 线上随访失访任务数
        String taskType = Constants.TASK_TYPE_SCHEME_SCHEDULE;
        int outTotal = 0;// 门诊随访总任务数
        int onlineTotal = 0;// 线上随访总任务数
        int iTaskSeq = 0;
        String ptSourceType = pt.getSourceType();
        // 实例化门诊任务
        while (true) {
            ft = taskList.get(0);
            iTaskSeq = ft.getSeqNo();
            int iCycleDay = ft.getCycleDay();
            if (Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                outTotal++;
            } else {
                onlineTotal++;
            }

            // pt_task_info
            if (StringUtils.isEmpty(ft.getNextTaskId())) {
                nextTaskId = "";
            } else {
                nextTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
            }
            PatientTask ptk = new PatientTask();
            String ptk_id = currTaskId;
            // taskIdList.add(ptk_id);
            ptk.setId(ptk_id);
            ptk.setNextTaskId(nextTaskId);
            currTaskId = nextTaskId;

            // 触发方式
            String executeType = ft.getExecuteType();
            executeMapIn.put("executeType", executeType);
            executeMapIn.put("taskSeq", iTaskSeq);
            executeMapIn.put("cycleDay", iCycleDay);
            executeMapIn.put("executeDay", ft.getExecuteDay());

            String executeTime = "";
            if (!StringUtils.isEmpty(birthDay)) {// 微信产妇建档 可能没有生日选项
                executeTime = ToolUtils.getExecuteTime(executeMapIn);
                iWinDay = ft.getWindowDay();
                suffWinDay = ft.getSuffixWindowDay();
                endTime = DateUtil.calcDay(executeTime, "+", suffWinDay);
            } else {
                executeTime = currDay;
                endTime = currDay;
            }

            if (Constants.TASK_SEQ_FOR_INIT == iTaskSeq && Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                taskId_0 = ptk_id;
                iWinDay = 0;// 建档任务无窗口期
                suffWinDay = 0;
                // 建档任务默认完成，并记下录入人姓名
                ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_FINISH);
                ptk.setUpdateAuname(authorName);
                ptk.setUpdateAuthor(authorId);
            } else if (endTime.compareTo(currDay) < 0) {
                // 已过期
                ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_EXPIRED);
                if (Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                    lostNum++;
                } else {
                    onlineLostNum++;
                }
                // 入失访记录表
                PtLostRd prdVo = new PtLostRd();
                prdVo.setAuthorId(authorId);
                prdVo.setCreateTime(updateTime);
                prdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_LOST_ID));
                prdVo.setLostDate(endTime);
                prdVo.setPtSchemeid(ptQueueSchemeId);
                prdVo.setQueueId(queueId);
                prdVo.setReasonId("");
                prdVo.setTaskId(ptk_id);
                prdVo.setTaskName(ft.getTaskName());
                prdVo.setUpdateAccept(updateAccept);
                prdVo.setUpdateTime(updateTime);
                prdVo.setUserId(userId);
                patientTaskDao.savePatientLostInfo(prdVo);
            } else {
                // 未开始
                ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_INIT);
            }

            ptk.setAuthorId(authorId);
            ptk.setExecuteTime(executeTime);
            ptk.setBeginTime(DateUtil.calcDay(executeTime, "-", iWinDay));
            ptk.setEndTime(endTime);
            ptk.setCreateTime(updateTime);
            ptk.setExecuteDay(ft.getExecuteDay());
            ptk.setExecuteType(executeType);
            ptk.setInformFlag(ft.getInformFlag());
            ptk.setPtSchemeid(ptQueueSchemeId);
            ptk.setSeqNo(iTaskSeq);
            ptk.setTaskIntro(ft.getTaskIntro());
            ptk.setTaskName(ft.getTaskName());
            ptk.setUpdateTime(updateTime);
            ptk.setUserId(pt.getId());
            ptk.setWarnDay(ft.getWarnDay());
            ptk.setWindowDay(iWinDay);
            ptk.setQueueId(queueId);
            ptk.setUpdateAccept(updateAccept);
            if (!StringUtils.isBlank(ft.getTaskType())) {
                ptk.setTaskType(ft.getTaskType());// 方案中任务
            } else {
                ptk.setTaskType(Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
            }
            // 诊间扫码渠道建档，需要审核，modify by DemonLee 2018.3.8
            ptk.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_INIT);// 初始化审核状态
            if (Constants.TASK_SEQ_FOR_INIT == iTaskSeq && StringUtils.isNotBlank(ptSourceType)) {
                // 首次建档任务
                if (Constants.PATIENT_SOURCE_TYPE_DOOR.equals(ptSourceType)) {
                    // 门诊建档自动审核通过
                    ptk.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_NORMAL);
                } else if (Constants.PATIENT_SOURCE_TYPE_SCAN.equals(ptSourceType)) {
                    // 诊间扫码建档则待审核
                    ptk.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_CHECKING);
                } else {
                    // 后续待扩展
                }
            }
            ptTaskList.add(ptk);

            // 查询当前任务对应的任务内容
            HashMap<String, Object> taskContentParam = new HashMap<String, Object>();
            taskContentParam.put("taskId", ft.getId());
            taskContentParam.put("schemeVersionid", schemeVersionId);
            List<FollowTaskContent> taskContList = followTaskContDao.selectByTaskId(taskContentParam);
            if (null == taskContList || 0 == taskContList.size()) {
                continue;
            }

            FollowTaskContent ftc = new FollowTaskContent();
            int tc = 0;
            for (; tc < taskContList.size(); tc++) {
                ftc = taskContList.get(tc);

                // 获取内容模板
                Map<String, Object> templMap = new HashMap<String, Object>();
                templMap.put("id", ftc.getTemplId());
                List<ContentTempl> ctList = contentTemplDao.selectTemplById(templMap);
                if (null == ctList || 0 == ctList.size()) {
                    throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST, "查询任务内容模板记录为空！");
                }
                ContentTempl conVo = ctList.get(0);

                // 获取内容模板版本
                HashMap<String, Object> contVerMap = new HashMap<String, Object>();
                contVerMap.put("templId", ftc.getTemplId());
                contVerMap.put("templVersion", ftc.getTemplVersion());
                List<ContentTemplVersion> ctvList = contentTemplDao.selectContentDataNoTextByTempl(contVerMap);
                if (null == ctvList || 0 == ctvList.size()) {
                    throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLVERSION_NOT_EXIST,
                            "查询任务内容模板版本记录为空！");
                }
                ContentTemplVersion ctv = ctvList.get(0);

                // pt_taskcontent_info
                String ptkc_id = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTID);
                PatientTaskContent ptc = new PatientTaskContent();
                ptc.setCreateTime(updateTime);
                ptc.setUpdateTime(updateTime);
                ptc.setId(ptkc_id);
                ptc.setTaskId(ptk_id);
                ptc.setTemplVersionid(ctv.getId());
                ptc.setUpdateAccept(updateAccept);
                ptc.setTemplType(conVo.getTemplType());
                ptc.setUserId(userId);
                ptc.setPtSchemeid(ptQueueSchemeId);
                ptc.setSeqNo(conVo.getSeqNo());

                ptTaskContentList.add(ptc);
            }

            int breakFlag = 0;
            if (StringUtils.isEmpty(ft.getNextTaskId())) {
                breakFlag = 1;
            } else {
                taskQueryParam.put("taskId", ft.getNextTaskId());
                taskList = followTaskDao.selectFollowTaskByScheVerAndId(taskQueryParam);
                if (CollectionUtils.isEmpty(taskList)) {
                    breakFlag = 1;
                }
            }
            if (1 == breakFlag) {
                if (Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                    // 继续实例化线上随访任务
                    taskType = Constants.TASK_TYPE_SCHEME_TEMP;
                    taskQueryParam.put("schemeVersionid", schemeVersionId);
                    taskQueryParam.put("taskType", Constants.TASK_TYPE_SCHEME_TEMP);// 1：线上随访
                    taskQueryParam.put("seqNo", Constants.TASK_SEQ_FOR_FIRST);
                    taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
                    if (CollectionUtils.isEmpty(taskList)) {
                        break;
                    }
                    taskQueryParam.remove("seqNo");
                    currTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
                } else if (Constants.TASK_TYPE_SCHEME_TEMP.equals(taskType)) {
                    break;
                }
            }
        }
        retOut.put("ptTaskSize", outTotal);
        retOut.put("lostNum", lostNum);
        retOut.put("onlineLostNum", onlineLostNum);
        retOut.put("onlineTotal", onlineTotal);

        // 批量插入，提高效率
        patientTaskDao.savePatientTaskBatch(ptTaskList);
        if (ptTaskContentList.size() > 0) {
            patientTaskConDao.savePatientTaskContentBatch(ptTaskContentList);
        }

        // 问卷类型（兼容以前，将门诊和诊间扫码渠道加入判断）
        // 该字段按照最新的统一数据编码，后续可能没有用，这里只是为了兼容以前业务
        // modify by DemonLee 2018.3.9
        String templTypeStr = "";
        if (Constants.OP_TYPE_DOOR.equals(opType) || Constants.PATIENT_SOURCE_TYPE_DOOR.equals(ptSourceType)
                || Constants.PATIENT_SOURCE_TYPE_SCAN.equals(ptSourceType)) {
            templTypeStr = Constants.QUESTIONNAIRE_TYPE_0;
        } else {
            // 非门诊问卷，后续补充
            templTypeStr = "";
        }
        // 解析建档任务内容（问卷）
        if (null == quesMap || 0 == quesMap.size()) {
            logger.warn("无建档问卷问题--答案记录");
        } else {
            List<PatientContentData> ptcInList = new ArrayList<PatientContentData>();
            Iterator<String> iter = quesMap.keySet().iterator();
            while (iter.hasNext()) {
                PatientContentData pcdVo = new PatientContentData();
                String queskey = iter.next();
                Object obj = quesMap.get(queskey);
//                logger.info("++++dealPtTaskIns() obj:"+obj.toString());
//                String quesvalue = (String) obj;
                String quesvalue = obj.toString();
                pcdVo.setContentId("");
                pcdVo.setCreateTime(updateTime);
                pcdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTDATAID));
                pcdVo.setQuestionAnswer(quesvalue);
                pcdVo.setQuestionId(queskey);
                pcdVo.setTaskId(taskId_0);
                pcdVo.setUpdateAccept(updateAccept);
                pcdVo.setUpdateTime(updateTime);
                pcdVo.setUpdateType(Constants.UPDATE_TYPE_INSERT);
                pcdVo.setUserId(userId);
                pcdVo.setPtSchemeid(ptQueueSchemeId);
                pcdVo.setTemplType(templTypeStr);
                pcdVo.setQueueId(queueId);
                pcdVo.setTenantId(tenantId);
                pcdVo.setSourceTypeCreate(ptSourceType);
                pcdVo.setSourceTypeUpdate(ptSourceType);
                ptcInList.add(pcdVo);
            }
            // 批量插入
            patientTaskConDao.savePatientTaskContentDataBatch(ptcInList);
            patientTaskConDao.savePatientTaskContentDataHisBatch(ptcInList);
        }
        retOut.put("taskId_0", taskId_0);

        // 实例化线上主诉登记任务
        ptTaskList.clear();
        ptTaskContentList.clear();
        taskQueryParam.clear();
        taskList.clear();
        taskQueryParam.put("schemeVersionid", schemeVersionId);
        taskQueryParam.put("taskType", Constants.TASK_TYPE_NONSCHEME_REALTIME);// 2：线上主诉登记
        taskQueryParam.put("seqNo", Constants.TASK_SEQ_FOR_FIRST);
        taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
        if (!CollectionUtils.isEmpty(taskList)) {
            ft = taskList.get(0);
            String ruleType = "";

            Map<String, Object> ruleInMap = new HashMap<String, Object>();
            ruleInMap.put("taskId", ft.getId());
            ruleInMap.put("schemeVersionid", schemeVersionId);
            List<FuTaskRule> taskRuleList = fuTaskRuleDao.getTaskRuleByUnq(ruleInMap);
            if (!CollectionUtils.isEmpty(taskRuleList)) {
                ruleType = taskRuleList.get(0).getRuleType();
            }
            if (StringUtils.isEmpty(ruleType)) {
                // 默认通用规则
                ruleType = Constants.TASK_TYPE_SCHEME_SELFREPORT_COMMON;
            }

            // pt_task_info
            String ptk_id = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
            PatientTask ptk = new PatientTask();
            ptk.setRuleType(ruleType);
            ptk.setId(ptk_id);
            ptk.setNextTaskId("");

            // 触发方式
            String executeType = ft.getExecuteType();
            String executeTime = currDay;
            iWinDay = ft.getWindowDay();
            suffWinDay = ft.getSuffixWindowDay();
            endTime = DateUtil.calcDay(executeTime, "+", suffWinDay);
            ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_INIT);

            ptk.setAuthorId(authorId);
            ptk.setExecuteTime(executeTime);
            ptk.setBeginTime(DateUtil.calcDay(executeTime, "-", iWinDay));
            ptk.setEndTime(endTime);
            ptk.setCreateTime(updateTime);
            ptk.setExecuteDay(ft.getExecuteDay());
            ptk.setExecuteType(executeType);
            ptk.setInformFlag(ft.getInformFlag());
            ptk.setPtSchemeid(ptQueueSchemeId);
            ptk.setSeqNo(Constants.TASK_SEQ_FOR_FIRST);
            ptk.setTaskIntro(ft.getTaskIntro());
            ptk.setTaskName(ft.getTaskName());
            ptk.setUpdateTime(updateTime);
            ptk.setUserId(pt.getId());
            ptk.setWarnDay(ft.getWarnDay());
            ptk.setWindowDay(iWinDay);
            ptk.setQueueId(queueId);
            ptk.setUpdateAccept(updateAccept);
            ptk.setTaskType(ft.getTaskType());
            ptk.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_INIT);// 初始化审核状态

            // 查询当前任务对应的任务内容
            HashMap<String, Object> taskContentParam = new HashMap<String, Object>();
            taskContentParam.put("taskId", ft.getId());
            taskContentParam.put("schemeVersionid", schemeVersionId);
            List<FollowTaskContent> taskContList = followTaskContDao.selectByTaskId(taskContentParam);
            if (CollectionUtils.isEmpty(taskContList)) {
                logger.error("【" + ft.getId() + "】对应任务内容未配置！");
                throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASKCONTENT_NOT_EXIST, "任务内容未配置！");
            }

            FollowTaskContent ftc = new FollowTaskContent();
            int tc = 0;
            String beginDate = "";
            String endDate = "";
            for (; tc < taskContList.size(); tc++) {
                ftc = taskContList.get(tc);

                // 获取内容模板
                Map<String, Object> templMap = new HashMap<String, Object>();
                templMap.put("id", ftc.getTemplId());
                List<ContentTempl> ctList = contentTemplDao.selectTemplById(templMap);
                if (CollectionUtils.isEmpty(ctList)) {
                    logger.error("【" + ftc.getTemplId() + "】查询任务内容模板记录为空！");
                    throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST, "查询任务内容模板记录为空！");
                }
                ContentTempl conVo = ctList.get(0);

                // 获取内容模板版本
                HashMap<String, Object> contVerMap = new HashMap<String, Object>();
                contVerMap.put("templId", ftc.getTemplId());
                contVerMap.put("templVersion", ftc.getTemplVersion());
                List<ContentTemplVersion> ctvList = contentTemplDao.selectContentDataNoTextByTempl(contVerMap);
                if (CollectionUtils.isEmpty(ctvList)) {
                    logger.error("【" + ftc.getTemplId() + ", " + ftc.getTemplVersion() + "】查询任务内容模板版本记录为空！");
                    throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLVERSION_NOT_EXIST,
                            "查询任务内容模板版本记录为空！");
                }
                ContentTemplVersion ctv = ctvList.get(0);

                // pt_taskcontent_info
                PatientTaskContent ptc = new PatientTaskContent();
                ptc.setCreateTime(updateTime);
                ptc.setUpdateTime(updateTime);
                ptc.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTID));
                ptc.setTaskId(ptk_id);
                ptc.setTemplVersionid(ctv.getId());
                ptc.setUpdateAccept(updateAccept);
                ptc.setTemplType(conVo.getTemplType());
                ptc.setUserId(userId);
                ptc.setPtSchemeid(ptQueueSchemeId);
                ptc.setSeqNo(conVo.getSeqNo());
                ptc.setRuleType(ruleType);
                ptc.setPriorityNo(ftc.getPriorityNo());

                // 通用版不需要考虑开始结束时间
                beginDate = currDay;
                endDate = currDay;
                if (!Constants.TASK_TYPE_SCHEME_SELFREPORT_COMMON.equals(ruleType)) {
                    // 按月龄来，需要计算
                    int beginDay = ftc.getBeginDay();
                    int endDay = ftc.getEndDay();
                    Map<String, Object> ruleCalcIn = new HashMap<String, Object>();
                    ruleCalcIn.put("beginDay", beginDay);
                    ruleCalcIn.put("endDay", endDay);
                    ruleCalcIn.put("ruleType", ruleType);
                    ruleCalcIn.put("birthday", birthDay);
                    ruleCalcIn.put("expectedDay", pt.getExpectedDay());
                    ruleCalcIn.put("currDay", currDay);
                    ruleCalcIn.put("prenDay", iPrenDay);
                    ruleCalcIn.put("ageDay", ToolUtils.getBirthAgeDay(birthDay));
                    ruleCalcIn.put("outHospitalDay", servParamMap.get("outHospitalDay"));
                    Map<String, Object> ruleCalcOut = ToolUtils.getTaskRuleTime(ruleCalcIn);
                    beginDate = (String) ruleCalcOut.get("beginDate");
                    endDate = (String) ruleCalcOut.get("endDate");
                }
                ptc.setBeginDate(beginDate);
                ptc.setEndDate(endDate);

                ptTaskContentList.add(ptc);
            }

            // 批量插入，提高效率
            patientTaskDao.save(ptk);
            if (ptTaskContentList.size() > 0) {
                patientTaskConDao.savePatientTaskContentBatch(ptTaskContentList);
            }
        }
        // 记录历史轨迹
        HashMap<String, Object> taskHisParam = new HashMap<String, Object>();
        taskHisParam.put("updateAccept", updateAccept);
        taskHisParam.put("updateType", Constants.UPDATE_TYPE_INSERT);
        taskHisParam.put("ptSchemeid", ptQueueSchemeId);
        taskHisParam.put("updateTime", updateTime);
        patientTaskDao.savePatientTaskHisByPtSchemeid(taskHisParam);

        return retOut;
    }

    /**
     * 患者基本信息校验及入表
     */
    public Map<String, Object> dealPtBasicInfo(Map<String, Object> paramIn) throws Exception {
        logger.warn("---begin dealPtBasicInfo---" + paramIn.toString());
        Map<String, Object> retOut = new HashMap<String, Object>();
        Map<String, Object> servParamMap = new HashMap<String, Object>(paramIn);
        String updateTime = (String) servParamMap.get("updateTime");
        String updateAccept = (String) servParamMap.get("updateAccept");
        String phoneNo = (String) servParamMap.get("phoneNo");
        String userName = (String) servParamMap.get("userName");
        String tenantId = (String) servParamMap.get("tenantId");
        Patient pt = (Patient) servParamMap.get("patient");
        String queueId = (String) servParamMap.get("queueId");
        String authorId = (String) servParamMap.get("authorId");
        String ptAccountId = (String) servParamMap.get("ptAccountId");
        String idCard = (String) servParamMap.get("idCard");
        String wechat_id = (String) servParamMap.get("wechat_id");
        String birthday = null;
        if (null != servParamMap.get("birthday")) {
            birthday = servParamMap.get("birthday").toString();
        }

        Map<String, Object> qryPtMap = new HashMap<String, Object>();
        qryPtMap.put("phoneNo", phoneNo);
        qryPtMap.put("userName", userName);
        qryPtMap.put("tenantId", tenantId);
        qryPtMap.put("birthday", birthday);
        // 不同类型用户
        qryPtMap.put("userType", servParamMap.get("userType"));
        List<Patient> ptList = null;
        if (tenantId.equals("gzykdxfsdsyyta001") && null != birthday) {
            //这里是GY3Y的处理方法。
            ptList = patientDao.selectByBirthdayAndName(qryPtMap);
        } else {
            //其他医院的处理方法。
            ptList = patientDao.selectByPhoneNo(qryPtMap);
        }
        String userId = "";
        // 门诊扫码同步过来 用传入的userId
        String scanUserId = pt.getId();

        int redisFlag = 0;
        // 第一次入：（1）新患者，（2）当前租户下的新患者
        if (CollectionUtils.isEmpty(ptList)) {
            // 用基本租户再查
            int userExistFlag = 0;
            qryPtMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
            ptList = patientDao.selectByPhoneNo(qryPtMap);

            // 扫码同步用户信息时 有userId传入
            if (StringUtils.isEmpty(scanUserId)) {
                if (!CollectionUtils.isEmpty(ptList)) {
                    userId = ptList.get(0).getId();
                    userExistFlag = 1;
                } else {
                    userId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_USERID);
                }
            } else {
                userId = scanUserId;
            }

            /**
             *将用户姓名转成拼音入表
             *2018-01-11
             * wuyz
             **/
            String pinyin = ToolUtils.getEname(userName);//将姓名转成汉语拼音
            String jianpin = ToolUtils.getNameInitial(userName);//将姓名转成简拼
            pt.setNamePinyin(pinyin);
            pt.setNameInitial(jianpin);
            // 入患者信息表pt_user_info
            pt.setId(userId);
            pt.setAccountId(ptAccountId);
            if (0 == userExistFlag) {
                pt.setTenantId(Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
                patientDao.savePatientInfo(pt);// 基本患者信息(同步APP用该信息）
            }
            pt.setTenantId(tenantId);

            patientDao.savePatientInfo(pt);// 该租户下的基本患者信息
            // 历史表
            Map<String, Object> userHisMap = new HashMap<String, Object>();
            userHisMap.put("userId", userId);
            userHisMap.put("updateTime", updateTime);
            userHisMap.put("updateType", Constants.UPDATE_TYPE_INSERT);
            userHisMap.put("updateAccept", updateAccept);
            userHisMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
            patientDao.savePatientHisInfo(userHisMap);
            userHisMap.put("tenantId", tenantId);
            patientDao.savePatientHisInfo(userHisMap);

            // 入患者扩展信息pt_userextend_info
            Object extendObj = servParamMap.get("extendInfo");
            if (null != servParamMap.get("extendInfo")) {
                Map<String, Object> extendMap = ToolUtils.typeCast(extendObj);
                List<PtUserextendInfo> ptAcBatchList = new ArrayList<PtUserextendInfo>();
                Iterator<String> iter = extendMap.keySet().iterator();
                String key = "";
                while (iter.hasNext()) {
                    key = iter.next();

                    PtUserextendInfo ptExtVo = new PtUserextendInfo();
                    ptExtVo.setUserId(userId);
                    ptExtVo.setAuthorId(authorId);
                    ptExtVo.setCreateTime(updateTime);
                    ptExtVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_SYSTEMID));
                    ptExtVo.setParamName(key);
                    ptExtVo.setParamValue("" + extendMap.get(key));
                    if ("alternateNo".equals(key)) {
                        ptExtVo.setRemark(phoneNo);
                    } else {
                        ptExtVo.setRemark("");
                    }
                    ptExtVo.setUpdateTime(updateTime);
                    ptExtVo.setQueueId(queueId);
                    ptExtVo.setTenantId(tenantId);
                    ptAcBatchList.add(ptExtVo);
                }
                ptExtendDao.savePatientExtendBatch(ptAcBatchList);
            }

            redisFlag = 1;
        } else {
            pt = ptList.get(0);
            userId = pt.getId();
            qryPtMap.put("userId", userId);
            qryPtMap.put("phoneNo", phoneNo);
            qryPtMap.put("userName", pt.getUserName());
            qryPtMap.put("wechat_id", wechat_id);
            qryPtMap.put("tenantId", tenantId);
            qryPtMap.put("idCard", idCard);
            // 微信id更新接口
            if (!StringUtils.isBlank(pt.getWechat_id())) {
                patientDao.updateWechatId(qryPtMap);
                // 增加入历史记录
                Map<String, Object> userHisMap = new HashMap<String, Object>();
                userHisMap.put("userId", userId);
                userHisMap.put("updateTime", updateTime);
                userHisMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
                userHisMap.put("updateAccept", updateAccept);
                userHisMap.put("tenantId", tenantId);
                patientDao.savePatientHisInfo(userHisMap);
            }
            logger.warn("该患者[" + pt.getUserName() + "]已经建档，建档时间==[" + pt.getCreateTime() + "]！");
        }

        retOut.put("userId", userId);
        retOut.put("redisFlag", redisFlag);
        retOut.put("patient", pt);
        return retOut;
    }

    // 患者添加
    @Transactional
    public Map<String, Object> registerPatient(Map<String, Object> servParamMap) throws Exception {
        logger.warn("registerPatient arg==" + servParamMap.toString());

        Patient pt = (Patient) servParamMap.get("patient");

        String deptId = (String) servParamMap.get("deptId");
        String queueId = (String) servParamMap.get("queueId");
        String updateTime = (String) servParamMap.get("updateTime");
        String authorId = (String) servParamMap.get("authorId");
        String updateAccept = (String) servParamMap.get("updateAccept");
        String tenantId = (String) servParamMap.get("tenantId");
        String authorName = (String) servParamMap.get("authorName");
        String opCode = (String) servParamMap.get("opCode");
        String opType = (String) servParamMap.get("opType");
        String sourseType = (String) servParamMap.get("sourseType");
        String phoneNo = pt.getPhoneNo();
        Map<String, Object> quesMap = ToolUtils.typeCast(servParamMap.get("contentData"));
        Map<String, Object> mapIn = ToolUtils.typeCast(servParamMap.get("extendInfo"));

        String fromQueueId = (null == servParamMap.get("fromQueueId")) ? null
                : String.valueOf(servParamMap.get("fromQueueId"));
        String fromQueueSchemeId = (String) servParamMap.get("fromQueueSchemeId");

        // 先锁表，防止同一个队列并发添加患者
        FollowQueue upQueue = new FollowQueue();
        upQueue.setId(queueId);
        upQueue.setUpdateTime(updateTime);
        int queRet = queueDao.updateQueue(upQueue);
        if (0 == queRet) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }

        // 队列信息校验
        HashMap<String, Object> queueMap = new HashMap<String, Object>();
        queueMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueMap);
        if (null == queueList || 0 == queueList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }
        String queueName = queueList.get(0).getQueueName();
        FollowQueue fq = (FollowQueue) queueList.get(0);
        if (!Constants.QUEUE_STATUS_NOMAL.equals(fq.getQueueStatus())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_STATUS_IRREGULAR, "当前加入的队列状态不正常，无法添加患者！"));
        }
        // 扫码建档，队列审核状态
        String auditType = fq.getAuditType();
        if (StringUtils.isBlank(auditType)) {
            auditType = "";
        }
        /*
         * 租户id必须存在，一个用户加入某个租户下的队列，则记录一份用户信息， 同时记录一份基本用户信息， 基本用户信息tenant_id=0
         * add by DemonLee, 2017.6.11
         */
        if (StringUtils.isEmpty(tenantId)) {
            // session中没有，则从队列下获取，队列下没有，则报错
            tenantId = fq.getTenantId();
            if (StringUtils.isEmpty(tenantId)) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_FOR_TENANT_NOT_EXIST,
                        "租户id为空或未配置，无法添加患者！"));
            }
            servParamMap.put("tenantId", tenantId);
        }

        int targetNum = fq.getTargetNum();// 队列目标人数
        int currNum = fq.getCurrNum();// 队列当前人数
        if (Constants.QUEUE_TARGET_NUM_INFINITE == targetNum) {
            // -1表示不设上限，可以任意添加患者
        } else if (targetNum <= 0) {
            // 其他小于等于0的数不合理，异常退出
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_TARGETNUM_CONFIG_ERROR,
                    "当前队列【" + fq.getQueueName() + "】目标人数配置错误，无法添加新患者！"));
        } else if (currNum >= targetNum) {
            // 当前人数已达到目标人数，无法继续添加患者
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_TARGETNUM_LIMIT,
                    "当前队列【" + fq.getQueueName() + "】人数已达到上限，无法添加新患者！"));
        }

        // 校验账户信息
        String ptAccountId = "";// 账号id
        HashMap<String, Object> qryPtMap = new HashMap<String, Object>();
        qryPtMap.put("phoneNo", phoneNo);
        List<PtAccountInfo> ptAcList = ptAccountDao.selectPtAccountByPhoneNo(qryPtMap);
        if (null != ptAcList && 0 != ptAcList.size()) {
            PtAccountInfo ptAcVo = ptAcList.get(0);
            ptAccountId = ptAcVo.getId();
        } else {
            ptAccountId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_ACCOUNTID);
            PtAccountInfo ptAcVo = new PtAccountInfo();
            ptAcVo.setAccountName((String) servParamMap.get("matherName"));// 暂填母亲姓名
            ptAcVo.setAuthorId(authorId);
            ptAcVo.setCreateTime(updateTime);
            ptAcVo.setId(ptAccountId);
            ptAcVo.setPhoneNo(phoneNo);
            ptAcVo.setRemark("建档新增");
            ptAcVo.setUpdateTime(updateTime);
            ptAccountDao.savePatientAccountInfo(ptAcVo);
        }

        // 校验患者信息（是否已经建档）
        Map<String, Object> userInMap = new HashMap<String, Object>();
        userInMap.put("updateTime", updateTime);
        userInMap.put("updateAccept", updateAccept);
        userInMap.put("phoneNo", phoneNo);
        userInMap.put("userName", pt.getUserName());
        userInMap.put("tenantId", tenantId);
        userInMap.put("patient", pt);
        userInMap.put("queueId", queueId);
        userInMap.put("authorId", authorId);
        userInMap.put("ptAccountId", ptAccountId);
        userInMap.put("extendInfo", mapIn);
        userInMap.put("userType", servParamMap.get("userType"));
        userInMap.put("birthday", servParamMap.get("birthday"));

        Map<String, Object> userOutMap = this.dealPtBasicInfo(userInMap);
        String userId = (String) userOutMap.get("userId");
        int redisFlag = (Integer) userOutMap.get("redisFlag");
        if (null != userOutMap.get("patient")) {
            pt = (Patient) userOutMap.get("patient");
            servParamMap.put("patient", pt);
        }

        // 入操作流水记录表 ia_operation_record
        String opUserType = Constants.OPCODE_TYPE_DOCTOR;
        if (Constants.OP_TYPE_SELF.equals(pt.getSourceType())) {
            opUserType = Constants.OPCODE_TYPE_PATIENT;
        }
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", pt.getUserName());
        paramRecord.put("userId", userId);
        paramRecord.put("queueId", queueId);
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);

        if (Constants.OP_CODE_1004.equals(opCode)) {// 队列患者转移
            paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_11);
        } else if ((Constants.OP_CODE_1000.equals(opCode))) {
            paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_7);
        }
        paramRecord.put("opUsertype", opUserType);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        if (StringUtils.isBlank((String) servParamMap.get("opNote"))) {
            String remark = "患者" + pt.getUserName() + "通过app进行主诉登记";
            paramRecord.put("remark", remark);
        } else {
            paramRecord.put("remark", (String) servParamMap.get("opNote"));
        }
        paramRecord.put("opType", opType);

        // 校验患者是否已经加入过该队列
        HashMap<String, Object> qryPqsMap = new HashMap<String, Object>();
        qryPqsMap.put("userId", userId);
        qryPqsMap.put("queueId", queueId);

        List<String> statulist = new ArrayList<String>();// 查询出暂停和正常 两个状态
        // ,如果查到暂停状态 则提示去恢复
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_SUSPEND);
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT); // 待审核状态
        // 提示去审批
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_ADVANCE);
        qryPqsMap.put("status", statulist);

        List<PatientQueueScheme> pqsList = patientQueueSchemeDao.selectByUserId(qryPqsMap);
        if (null != pqsList && 0 != pqsList.size()) {
            if (Constants.PATIENT_QUEUESCHEME_USER_STATUS_SUSPEND.equals(pqsList.get(0).getUserStatus())) {
                logger.error("该患者[" + pt.getUserName() + "]为暂停状态，可直接恢复！");
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_STATUS_SUSPEND,
                        "该患者[" + pt.getUserName() + "]为暂停状态，请恢复患者为管理状态！"));
            } else if (Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT.equals(pqsList.get(0).getUserStatus())) {
                logger.error("该患者[" + pt.getUserName() + "]为待审核状态，请审批完再添加！");
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_STATUS_AUDIT,
                        "该患者[" + pt.getUserName() + "]为待审核状态，请进入审批列表审批即可"));
            } else {
                logger.error("患者[" + pt.getUserName() + "]已经加入[" + fq.getQueueName() + "]，请不要重复加入！");
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_ALREADY_EXIST,
                        "患者[" + pt.getUserName() + "]已经加入[" + fq.getQueueName() + "]，请不要重复加入！"));
            }
        }

        // 查询方案版本
        String schemeId = fq.getSchemeId();
        String VersionId = "";
        if (!StringUtils.isBlank(schemeId)) {
            VersionId = registerQuery(schemeId);
        }
        // 入患者队列信息表 pt_queuescheme_info
        final String schemeVersionId = VersionId;
        final String ptQueueSchemeId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTSCHEMEID);
        String cardStatus = (String) servParamMap.get("card_status");
        String cardType = (String) servParamMap.get("card_type");
        String cardNo = (String) servParamMap.get("card_no");

        PatientQueueScheme pts = new PatientQueueScheme();
        pts.setId(ptQueueSchemeId);
        pts.setAuthorId(authorId);
        pts.setCreateTime(updateTime);
        pts.setUpdateTime(updateTime);
        pts.setQueueId(queueId);
        pts.setSchemeId(schemeId);
        pts.setSchemeVersionid(schemeVersionId);
        pts.setUserId(pt.getId());
        pts.setTotalNum(0);
        pts.setUpdateAccept(updateAccept);
        pts.setUpdateAuthor(authorId);
        pts.setFinishNum(1);// 建档任务默认完成
        pts.setCardNo(cardNo);
        pts.setCardStatus(cardStatus);
        pts.setCardType(cardType);
        pts.setTenantId(tenantId);
        // 诊间扫码渠道建档，需要审核，modify by DemonLee 2018.3.7
        if (queueId.contains("-YZDL")) {
            pts.setUserStatus(Constants.PATIENT_QUEUESCHEME_USER_STATUS_ADVANCE);
        } else {
            pts.setUserStatus(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        }

        pts.setConfirmFlag(Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CONFIRM_SUCCESS);
        //转归类型 20180329
        pts.setChangeStatus(Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CHANGE_STATUS);
        String ptSourceType = pt.getSourceType();
        if (StringUtils.isNotBlank(ptSourceType) && Constants.PATIENT_SOURCE_TYPE_SCAN.equals(ptSourceType)) {
            // 审核类型为空或事后审核（事先审核走其他逻辑：预处理转正式）
            if (StringUtils.isBlank(auditType) || Constants.QUEUE_AUDIT_TYPE_FOR_PAST.equals(auditType)) {
                pts.setConfirmFlag(Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CONFIRM_INIT);
            }
        }

        // 查询问卷中是否有科研id（根据bs_static_param.type=1006配置的param_code匹配），需要入表pt_queuescheme_info.his_no字段
        if (null != quesMap && 0 != quesMap.size()) {
            // 查询配置表中的配置的id
            Map<String, Object> staticMap = new HashMap<String, Object>();
            staticMap.put("type", Constants.CONTENT_DATA_TYPE);
            List<Map<String, Object>> quesList = confCacheDao.selectBsStaticParamByCondition(staticMap);
            if (!CollectionUtils.isEmpty(quesList)) {
                List<String> hisNoList = new ArrayList<String>();
                int kk = 0;
                int quesSize = quesList.size();
                Map<String, Object> confMap = new HashMap<String, Object>();
                for (kk = 0; kk < quesSize; kk++) {
                    confMap = quesList.get(kk);
                    String confId = (String) quesMap.get(confMap.get("paramCode"));
                    if (!StringUtils.isBlank(confId)) {
                        hisNoList.add(confId);
                    }
                }
                // 目前只考虑最大3个研究id
                int inum = hisNoList.size();
                for (kk = 0; kk < inum; kk++) {
                    if (0 == kk) {
                        pts.setHisNo1(hisNoList.get(kk));
                    } else if (1 == kk) {
                        pts.setHisNo2(hisNoList.get(kk));
                    } else if (2 == kk) {
                        pts.setHisNo3(hisNoList.get(kk));
                    } else {
                        logger.warn("ignore his_no[" + kk + "]==" + hisNoList.get(kk));
                    }
                }
            }
        }

        // 更新队列当前人数+1 fu_queue_info
        FollowQueue fqueueVo = new FollowQueue();
        fqueueVo.setCurrNum(1);
        fqueueVo.setId(queueId);
        fqueueVo.setUpdateTime(updateTime);
        queueDao.updateQueue(fqueueVo);

        // 该队列有对应方案，则需要处理任务相关信息，否则不需要处理
        String taskId_0 = "";// 建档任务id
        if (!StringUtils.isEmpty(fq.getSchemeId())) {
            servParamMap.put("userId", userId);
            servParamMap.put("ptQueueSchemeId", ptQueueSchemeId);
            servParamMap.put("schemeVersionId", schemeVersionId);
            Map<String, Object> insOutMap = this.dealPtTaskIns(servParamMap);
            taskId_0 = (String) insOutMap.get("taskId_0");
            pts.setTotalNum((Integer) insOutMap.get("ptTaskSize"));
            pts.setLostNum((Integer) insOutMap.get("lostNum"));
            pts.setOnlineTotal((Integer) insOutMap.get("onlineTotal"));
            pts.setOnlineLost((Integer) insOutMap.get("onlineLostNum"));
        }
        HashMap<String, Object> insertPtQueueMap = new HashMap<String, Object>();
        insertPtQueueMap.put("id", pts.getId());
        insertPtQueueMap.put("updateTime", pts.getUpdateTime());
        insertPtQueueMap.put("updateAuthor", pts.getUpdateAuthor());
        insertPtQueueMap.put("updateAccept", pts.getUpdateAccept());
        insertPtQueueMap.put("updateType", Constants.UPDATE_TYPE_INSERT);
        patientQueueSchemeDao.savePatientQueueSchemeInfo(pts);
        patientQueueSchemeDao.insertPatientQueueSchemeHis(insertPtQueueMap);

        if (null != fromQueueId) {// 转移队列时 需将原队列患者状态置为转移状态 并插入一条历史记录
            Map<String, Object> updateQueueMap = new HashMap<String, Object>();
            updateQueueMap.put("id", fromQueueSchemeId);// ID
            updateQueueMap.put("queueId", fromQueueId);// ID
            updateQueueMap.put("updateTime", updateTime);
            updateQueueMap.put("updateAuthor", authorId);
            updateQueueMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_TRANSFER);
            updateQueueMap.put("oldStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
            updateQueueMap.put("updateAccept", updateAccept);
            updateQueueMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);

            // 转以后 更新原队列当前人数-1 fu_queue_info
            FollowQueue fromFqueueVo = new FollowQueue();
            fromFqueueVo.setCurrNum(1);
            fromFqueueVo.setId(fromQueueId);
            fromFqueueVo.setUpdateTime(updateTime);
            queueDao.updateQueueTransfer(fromFqueueVo);

            patientQueueSchemeDao.updatePtQueueSchemeRecord(updateQueueMap);
            patientQueueSchemeDao.insertPatientQueueSchemeHis(updateQueueMap);
        }

        // 若有建档任务，则将建档任务id入操作记录表
        if (!StringUtils.isEmpty(taskId_0)) {
            paramRecord.put("taskId", taskId_0);
        }
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        if (1 == redisFlag) {
            // redis记录今日新增患者
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.select(Constants.REDIS_DB_INDEX_PATIENT);

                ptQueueRedis.patientAddforQueue(queueId, jedis);
                ptQueueRedis.patientAddforAuthor(authorId, jedis);
                ptQueueRedis.patientAddforTenant(tenantId, jedis);
                if (!Constants.OP_TYPE_SELF.equals(pt.getSourceType())) {
                    ptQueueRedis.ptDoorAddforAuthor(authorId, jedis);
                }
            } catch (JedisConnectionException jex) {
                logger.error("redis连接异常..." + jex.getMessage());
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
            } finally {
                if (null != jedis) {
                    try {
                        jedis.close();
                        logger.warn("close redis connection...");
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_CLOSE_FAILED,
                                "Redis缓存关闭失败!"));
                    }
                }
            }
        }

        // 发消息到 患者注册 消息队列topic 放在最后处理
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("tenantId", tenantId);
        map.put("code", Constants.SMS_TEMPLATE_REGISTER_TYPE);
        String smsContent = "";
        if (!Constants.QUEUE_PATIENT_REGISTER_NOT_SEND_SMS.equals(fq.getSmsFlag())) {
            smsContent = bsSmsTemplateService.getSmsTemplateByCondition(map);
        }
        // 根据科室管理系统 科室id 查询 关联APP端 科室id 并同步给app
        DepartmentBasic dept = null;
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("departmentId", deptId);// 随访科室ID
        paramMap.put("queueId", queueId);
        paramMap.put("queueName", queueName);
        paramMap.put("sourseType", sourseType);
        String appDeptId = "";
        if (!StringUtils.isBlank(deptId)) {
            map.clear();
            map.put("deptId", deptId);
            dept = deparmentBasicDao.selectAppDeptId(map);
            if (null != dept) {
                appDeptId = String.valueOf(dept.getRefDepartmentId());
                paramMap.put("refDepartmentId", appDeptId);// app科室ID
            }
        }


        Map<String, Object> outRet = new HashMap<String, Object>();
        outRet.put("patientId", userId);
        outRet.put("ptSchemeId", ptQueueSchemeId);
        outRet.put("ptSchemeVersionId", schemeVersionId);
        return outRet;
    }

    // 患者队列信息接口实现
    public HashMap<String, Object> qryPatientQueueSchemeList(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        String flag = (String) argMap.get("flag");
        String tenantId = (String) argMap.get("tenantId");
        String fuzzyVar = (String) argMap.get("fuzzyVar");
        HashMap<String, Object> retMap = new HashMap<String, Object>();
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        retMap.put("total", 0);
        retMap.put("rows", pqsList);

        // 若有服务号码或患者姓名，则先获取患者id串（可能有多个）
        List<String> userIdArray = new ArrayList<String>();
        int qryUserFlag = 0;
        String phoneNo = (String) argMap.get("phoneNo");
        String userName = (String) argMap.get("userName");// 可以是姓氏或姓名
        String patientId = (String) argMap.get("patientId");// 用户id
        HashMap<String, Object> qryUserMap = new HashMap<String, Object>();
        if (null != phoneNo && !"".equals(phoneNo) && StringUtils.isEmpty(fuzzyVar)) {
            qryUserMap.put("phoneNo", phoneNo);
            qryUserFlag = 1;
        }
        if (null != userName && !"".equals(userName)) {
            argMap.put("userName", userName + "%");
        }
        if (null != patientId && !"".equals(patientId)) {
            argMap.put("patientId", patientId);
        }
        if (null != argMap.get("userId") && !"".equals(argMap.get("userId"))) {
            argMap.put("patientId", argMap.get("userId"));
        }
        if (1 == qryUserFlag) {
            List<Patient> ptList = patientDao.select(qryUserMap);
            if (null == ptList || 0 == ptList.size()) {
                logger.warn("无此患者信息...arg==" + qryUserMap.toString());
                return retMap;
            }
            int ipt = 0;
            for (; ipt < ptList.size(); ipt++) {
                Patient ptVo = ptList.get(ipt);
                // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                userIdArray.add(ptVo.getId());
            }
        }
        logger.warn("userIdArray==" + userIdArray.toString());

        // 根据当前登录账号获取，其可以查看的队列id（权限处理比较复杂，这里先简化）
        String authorId = (String) argMap.get("authorId");
        HashMap<String, Object> qryQueueMap = new HashMap<String, Object>();
        qryQueueMap.put("authorId", authorId);
        qryQueueMap.put("queueStatus", Constants.QUEUE_STATUS_NOMAL);// 队列状态正常
        qryQueueMap.put("tenantId", tenantId);
        qryQueueMap.put("queueTypePrivate", Constants.QUEUE_TYPE_PRIVATE);
        qryQueueMap.put("queueTypeTenant", Constants.QUEUE_TYPE_TENANT);
        qryQueueMap.put("queueTypePublic", Constants.QUEUE_TYPE_PUBLIC);

        List<FollowQueue> fqList = null;
        // 1：如果传入队列 则直接用队列查询 2：没有传入队列ID 则根据权限先查询 该用户有哪些队列权限 再查询
        String queueId = (String) argMap.get("queueId");
        String queueName = "";
        if (!StringUtils.isBlank(queueId)) {
            Map<String, Object> queueMap = new HashMap<String, Object>();
            queueMap.put("id", queueId); // 租户id先写死
            fqList = queueDao.selectById(queueMap);
        } else {
            List<Map<String, Object>> lists = IConfCacheDAO.selectAuthorId(qryQueueMap);
            if (lists != null && lists.size() > 0 && !"0".equals((String) argMap.get("showFlag"))) {
                fqList = queueDao.selectQueueIdByparentId(qryQueueMap);
                for (int j = 0; j < fqList.size(); j++) {
                    if (authorId.equals(fqList.get(j).getAuthorId())) {
                        queueName = fqList.get(j).getQueueName();
                    }
                }
            } else {
                fqList = queueDao.selectQueueIdByAuthority(qryQueueMap);
                //根据authorId过滤队列
                if (ObjectUtil.isNotEmpty(fqList)) {
                    List<String> queueIds = followQueueAuthorityDAO.getDuiLieByAuthorId(authorId);
                    fqList = fqList.stream().filter(item -> {
                        if (queueIds.contains(item.getId())) {
                            return true;
                        } else {
                            return false;
                        }
                    }).collect(Collectors.toList());
                }
            }
        }
        argMap.put("queueNameStr", queueName);

        if (null == fqList || 0 == fqList.size()) {
            logger.warn("该账号无可查看到的队列信息...arg==" + qryQueueMap.toString());
            return retMap;
        }
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.select(Constants.REDIS_DB_INDEX_CONFIG);
            List<String> queueIdArray = new ArrayList<String>();
            int fqt = 0;
            for (; fqt < fqList.size(); fqt++) {
                FollowQueue fqVo = fqList.get(fqt);
                // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                queueIdArray.add(fqVo.getId());
            }

            // 获取随访患者list
            argMap.put("queueIdIn", queueIdArray);
            if (0 != userIdArray.size()) {
                argMap.put("userIdIn", userIdArray);
            }

            // 今日待随访患者flag=0（即今天在窗口期内的患者都算）
            if ("0".equals(flag)) {
                retMap = this.listTodayPatientByCondition(argMap, jedis);
            } else if ("2".equals(flag)) {
                // 当前账号可以看到的所有患者list（flag=2）
                retMap = this.listAllPatientByCondition(argMap, jedis);
            } else if ("3".equals(flag)) {
                // flag=3 随访记录查询，每个随访的患者多次记录，只展示最后一次
                retMap = this.listPtFollowRecord(argMap, jedis);
            } else if ("4".equals(flag)) {
                // flag=4 随访记录查询，每个随访的患者多次记录，只展示最后一次
                argMap.remove("queueIdIn");
                argMap.remove("tenantId");
                retMap = this.listAllPatientByCondition(argMap, jedis);
            }

            if (retMap.get("rows") != null) {
                List<Map<String, Object>> tempList = (List<Map<String, Object>>) retMap.get("rows");
                for (Map<String, Object> patient : tempList) {
                    // true: 已结案 false: 未结案
                    //logger.info("==========查到"+patient.get("patientId")+"的closeCaseRecord数据: " + patient.get("closeCaseRecord"));
                    patient.put("closeCaseRecord", patient.get("closeCaseRecord") != null);
                    //脑卒中队列添加量表测试结果
                    //String followQueueId = (String)patient.get("followQueueId");
                    //if (followQueueId.contains("naocuzhong")){
                    //    String pid = (String)patient.get("patientId");
                    //    String psId = (String)patient.get("patientSchemeId");
                    //    Map<String, Object> map = new HashMap<>();
                    //    map.put("patientId",pid);
                    //    map.put("patientSchemeId",psId);
                    //    //根据患者id查询患者最近一次随访内容
                    //    List<PatientContentData> patientContentDataList = this.queryPatientRecentlyFollowRecord(map);
                    //    if (patientContentDataList!=null && patientContentDataList.size()>0){
                    //        patientContentDataList.stream().forEach(item->{
                    //            if (item.getQuestionId().equals("ncz_nczfxpj")){
                    //                String answer = item.getQuestionAnswer();
                    //                if (answer.contains("低危")){
                    //                    patient.put("nczfxpj","低危");
                    //                    return;
                    //                }
                    //                if (answer.contains("中危")){
                    //                    patient.put("nczfxpj","中危");
                    //                    return;
                    //                }
                    //                if (answer.contains("高危")){
                    //                    patient.put("nczfxpj","高危");
                    //                    return;
                    //                }
                    //            }
                    //        });
                    //    }
                    //}
                }
            }

        } catch (JedisConnectionException jex) {
            logger.error("redis连接异常..." + jex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
        } finally {
            if (null != jedis) {
                try {
                    jedis.close();
                    logger.warn("close redis connection...");
                } catch (Exception ex) {
                    ex.printStackTrace();
                    throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_CLOSE_FAILED,
                            "Redis缓存关闭失败!"));
                }
            }
        }
        if (!StringUtils.isBlank(queueId) && !CollectionUtils.isEmpty(fqList)) {
            retMap.put("followQueueName", fqList.get(0).getQueueName());
        }

        return retMap;
    }

    // 今日待门诊患者查询（单独封装一个组件）,modify by DemonLee 2018.3.6
    public HashMap<String, Object> listTodayPatientByCondition(Map<String, Object> mapIn, Jedis jedis)
            throws Exception {
        HashMap<String, Object> retMap = new HashMap<String, Object>();
        HashMap<String, Object> argMap = new HashMap<String, Object>(mapIn);

        String userStatus = (String) argMap.get("userStatus");
        int total = 0;
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        // 诊间扫码查询正常或待审核的患者, modify by DemonLee 2018.03.06
        List<String> userStatusList = new ArrayList<String>();
        userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
        // userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT);// 队列中待审核用户
        if (StringUtils.isBlank(userStatus)) {
            argMap.put("userStatusIn", userStatusList);
        }
        argMap.put("taskStatus", Constants.PATIENT_TASK_STATUS_INIT);// 未开始的任务
        argMap.put("endTime", DateUtil.getCurrDate());// 截止时间>=当前时间
        argMap.put("beginTime", DateUtil.getCurrDate());// 开始时间<=当前时间
        argMap.put("taskExistsFlag", "1");
        argMap.put("orderByStatusAndTime", "1");
        argMap.put("initTaskRev", "1");
        argMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务

        total = patientQueueSchemeDao.countTotalPtQueueNumByCondition(argMap);
        if (total > 0) {
            pqsList = patientQueueSchemeDao.selectPtQueueList(argMap);

            if (null == pqsList || 0 == pqsList.size()) {
                // 数据被删除或改变了
                total = 0;
            } else {
                HashSet<String> fristNameSet = new HashSet<String>();

                // 使用set容器对姓氏剔重
                int pq = 0;
                String pqsQueueId = "";
                String patientSchemeId = "";
                Map<String, Object> qryMapIn = new HashMap<String, Object>();
                Map<String, Object> qryMapOut = new HashMap<String, Object>();
                Map<String, Object> ptMapIn = new HashMap<String, Object>();
                for (; pq < pqsList.size(); pq++) {
                    Map<String, Object> pqsMap = pqsList.get(pq);
                    String firstName = (String) pqsMap.get("FirstName");
                    fristNameSet.add(firstName);

                    // 获取队列名称
                    pqsQueueId = (String) pqsMap.get("followQueueId");
                    qryMapIn.clear();
                    qryMapIn.put("queueId", pqsQueueId);
                    qryMapOut = getQueueName(qryMapIn, jedis);
                    pqsMap.put("followQueueName", qryMapOut.get("queueName"));

                    // 获取方案下所有任务的完成情况
                    pqsMap.put("taskAuditFlag", "N");// 是否存在待审核的任务，默认无
                    int ptsize = 0;
                    int kk = 0;
                    patientSchemeId = (String) pqsMap.get("patientSchemeId");

                    //获取高危信息登记等级
                    getGwSign(patientSchemeId, pqsMap);
                    ptMapIn.clear();
                    ptMapIn.put("ptSchemeId", patientSchemeId);
                    ptMapIn.put("seqNoOrderAsc", "1");
                    ptMapIn.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
                    List<Map<String, Object>> mapOutList = patientTaskDao.selectTaskStatusByPtSchemeId(ptMapIn);
                    if (CollectionUtils.isEmpty(mapOutList) || MapUtils.isEmpty(mapOutList.get(0))) {
                        // 无任务信息，异常情况
                        ptsize = Integer.parseInt("" + pqsMap.get("totalNum"));
                        if (ptsize <= 0) {
                            pqsMap.put("taskStatusArr", "[]");
                        } else {
                            StringBuffer strStatus = new StringBuffer();
                            strStatus.append("[");
                            for (kk = 0; kk < ptsize; kk++) {
                                strStatus.append("0,");
                            }
                            String strStr = strStatus.substring(0, strStatus.length() - 1);
                            pqsMap.put("taskStatusArr", strStr + "]");
                        }
                    } else {
                        pqsMap.put("taskStatusArr", mapOutList.get(0).get("taskStatusArr"));
                        Object scObj = (Object) mapOutList.get(0).get("auditStatusScore");
                        if (null != scObj) {
                            Integer auditStatusScore = Integer.parseInt(scObj.toString());
                            if (null != auditStatusScore && auditStatusScore > 0) {
                                pqsMap.put("taskAuditFlag", "Y");// 存在待审核或审核未通过的任务
                            }
                        }
                    }
                }

                StringBuffer firstNameValue = new StringBuffer();
                Iterator<String> itor = fristNameSet.iterator();
                while (itor.hasNext()) {
                    firstNameValue.append(itor.next());
                    firstNameValue.append(",");
                }
                retMap.put("FirstName", firstNameValue.substring(0, firstNameValue.length() - 1));
            }
        }

        retMap.put("total", total);
        retMap.put("rows", pqsList);

        return retMap;
    }

    // 全部患者查询（单独封装一个组件）,modify by DemonLee 2018.3.6
    public HashMap<String, Object> listAllPatientByCondition(Map<String, Object> mapIn, Jedis jedis) throws Exception {
        HashMap<String, Object> retMap = new HashMap<String, Object>();
        HashMap<String, Object> argMap = new HashMap<String, Object>(mapIn);

        String queueNameStr = (String) argMap.get("queueNameStr");
        String userStatus = (String) argMap.get("userStatus");
        String status = (String) argMap.get("status");
        int total = 0;
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();

        // 诊间扫码查询正常或待审核的患者, modify by DemonLee 2018.03.06
        String systemType = (String) argMap.get("systemType");
        if (StringUtils.isBlank(systemType)) {
            systemType = Constants.CLOUND_SYSTEM_TYPE_FOR_BOTH_FUOUT;
        }
        if (Constants.CLOUND_SYSTEM_TYPE_FOR_FOLLOW.equals(systemType)) {
            // 支撑随访任务和审核状态
            argMap.put("taskExistsFlag", "1");
        }
        List<String> auditStatusList = new ArrayList<String>();
        auditStatusList.add(Constants.PATIENT_TASK_AUDIT_STATUS_CHECKING);// 待审核
        auditStatusList.add(Constants.PATIENT_TASK_AUDIT_STATUS_NOTPASS);// 审核未通过
        List<String> userStatusList = new ArrayList<String>();
        userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
        // userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT);// 队列中待审核用户
        if (StringUtils.isBlank(userStatus) && StringUtils.isBlank(status)) {
            argMap.put("userStatusIn", userStatusList);
        }
        argMap.put("orderByStatusAndTime", "1");
        List<String> taskTypeInList = new ArrayList<String>();
        taskTypeInList.add(Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
        taskTypeInList.add(Constants.TASK_TYPE_SCHEME_TEMP);// 线上随访（暂时放开）
        argMap.put("taskTypeIn", taskTypeInList);

        // 根据孕周查询
        total = patientQueueSchemeDao.countTotalPtQueueNumByCondition(argMap);
        //港大需求：根据病人号查询。（Modified by Michael Zhu on 2022/06/03）
        int brhTotal = 0;
        List<String> userIdIn = new ArrayList<>();
        Object fuzzyVarObj = mapIn.get("fuzzyVar");
        if (null != fuzzyVarObj) {
            Map<String, Object> paraMap = new HashMap<>();
            final String fuzzyVar = fuzzyVarObj.toString();
            if (!fuzzyVar.isEmpty()) {
                final String answer = fuzzyVar.substring(0, fuzzyVar.length() - 1);
                paraMap.put("questionAnswer", answer);
                List<PatientContentData> brhList = patientTaskConDao.selectBRH(paraMap);
                brhTotal = brhList.size();
                for (PatientContentData pcd : brhList) {
                    userIdIn.add(pcd.getUserId());
                }
            }
        }
        if (total > 0 || brhTotal > 0) {
            pqsList = patientQueueSchemeDao.selectPtQueueList(argMap);
            if (null == pqsList || 0 == pqsList.size()) {
                argMap.remove("fuzzyVar");
                argMap.put("userIdIn", userIdIn);
                pqsList = patientQueueSchemeDao.selectPtQueueList(argMap);
            }
            if (null == pqsList || 0 == pqsList.size()) {
                // 数据被删除或改变了
                total = 0;
            } else {
                HashSet<String> fristNameSet = new HashSet<String>();
                int pq = 0;
                String pqsQueueId = "";
                String patientSchemeId = "";
                Map<String, Object> qryMapIn = new HashMap<String, Object>();
                Map<String, Object> qryMapOut = new HashMap<String, Object>();
                Map<String, Object> ptMapIn = new HashMap<String, Object>();
                Map<String, Object> newMapArg = new HashMap<String, Object>();
                for (; pq < pqsList.size(); pq++) {
                    Map<String, Object> pqsMap = pqsList.get(pq);
                    if ("true".equals(PropertiesUtils.getProperty("isReferral"))) {//开启转诊功能，查询转诊记录表相关信息
                        String userid = (String) pqsMap.get("patientId");
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("userId", userid);
                        Patient patient = this.getPatient(map);
                        String tenantId = patient.getTenantId();
                        map.clear();
                        map.put("id", tenantId);
                        List<Map<String, Object>> maps = fuReferralRecordDao.selectTenant(map);
                        Map<String, Object> objectMap = maps.get(0);
                        String name = (String) objectMap.get("name");
                        pqsMap.put("referralHosName", name);

                        String createAuthor = (String) pqsMap.get("createAuthor");
                        map.clear();
                        map.put("id", createAuthor);
                        Doctor doctor = doctorDao.selectById(map);
                        pqsMap.put("doctorName", doctor == null ? createAuthor : doctor.getDoctorName());
                    }

                    String createAuthor = (String) pqsMap.get("createAuthor");
                    Map map = new HashMap<String, String>();
                    map.put("id", createAuthor);
                    Doctor doctor = doctorDao.selectById(map);
                    pqsMap.put("createAuthor", doctor == null ? createAuthor : doctor.getDoctorName());
                    String firstName = (String) pqsMap.get("FirstName");
                    fristNameSet.add(firstName);

                    patientSchemeId = (String) pqsMap.get("patientSchemeId");

                    //获取高危信息登记等级
                    getGwSign(patientSchemeId, pqsMap);

                    // 获取队列名称
                    pqsQueueId = (String) pqsMap.get("followQueueId");
                    qryMapIn.clear();
                    qryMapIn.put("queueId", pqsQueueId);
                    qryMapOut = getQueueName(qryMapIn, jedis);
                    qryMapIn.put("id", pqsQueueId);
                    List<FollowQueue> flq = queueDao.selectById(qryMapIn);
                    pqsMap.put("followQueueName", qryMapOut.get("queueName"));
                    if (!StringUtils.isBlank(queueNameStr) && !queueNameStr.equals(qryMapOut.get("queueName"))
                            && Constants.LOST_REASON_TYPE_PRIVATE.equals(flq.get(0).getQueueType())) {
                        pqsMap.put("unchecked", "1");
                    } else {
                        pqsMap.put("unchecked", "0");
                    }
                    qryMapIn.put("patientSchemeId", (String) pqsMap.get("patientSchemeId"));
                    qryMapIn.put("userId", (String) pqsMap.get("patientId"));
                    // 微信月度评估兼容返回出生体重
                    List<PatientContentData> lists = patientTaskConDao.listCntDataByUserIdAndAcceptPrivate(qryMapIn);
                    if (!CollectionUtils.isEmpty(lists)) {
                        for (int j = 0; j < lists.size(); j++) {
                            if (Constants.QUESTION_ID_FOR_WEIGHT.equals(lists.get(j).getQuestionId())) {
                                pqsMap.put("weight", lists.get(j).getQuestionAnswer());
                            } else if (Constants.QUESTION_ID_FOR_LAST_MENSTRUATION_DATE.equals(lists.get(j).getQuestionId())) {
                                pqsMap.put(Constants.QUESTION_ID_FOR_LAST_MENSTRUATION_DATE, lists.get(j).getQuestionAnswer());
                            }
                        }
                    }
                    // 获取方案名称
                    qryMapIn.clear();
                    qryMapIn.put("schemeId", (String) pqsMap.get("schemeId"));
                    qryMapOut = getSchemeName(qryMapIn, jedis);
                    pqsMap.put("schemeName", qryMapOut.get("schemeName"));
                    //pqsMap.put("createTime", DateUtil.getTimeStampDay(pqsMap.get("createTime").toString()));
                    // 年龄
                    Object birthdayObj = (Object) pqsMap.get("birthday");
                    if (null != birthdayObj) {
                        String birthdayStr = String.valueOf(birthdayObj);
                        if (!StringUtils.isEmpty("" + pqsMap.get("pregnancyDay"))
                                && StringUtils.isNotBlank(birthdayStr)) {
                            String pregnancy = "" + pqsMap.get("pregnancyDay");
                            long correctAge = ToolUtils.getCorrect(String.valueOf(pqsMap.get("birthday")),
                                    Integer.parseInt(pregnancy));

                            Date date = new Date(correctAge);
                            pqsMap.put("age", ToolUtils.getAgeByBirthday(DateUtil.getDate_8(date)));
                            pqsMap.put("pregnancyWeek",
                                    ToolUtils.getPregnancyStr(Integer.parseInt("" + pqsMap.get("pregnancyDay"))));
                        } else if (StringUtils.isNotBlank(birthdayStr)) {
                            // 孕周为空则按正常年龄算
                            pqsMap.put("age", ToolUtils.getAgeByBirthday("" + pqsMap.get("birthday")));
                        } else {
                            pqsMap.put("age", "");
                        }
                    } else {
                        pqsMap.put("age", "");
                    }
                    //男女判断
                    String gender = pqsMap.get("gender").toString();
                    if ("男".equals(gender) || "N".equals(gender)) {
                        pqsMap.put("gender2", "男");
                    } else if (StringUtils.isNotEmpty(gender)) {
                        pqsMap.put("gender2", "女");
                    }
                    //转诊功能增加字段
                    String fileNo = "";
                    if (null != pqsMap.get("fileNo")) {
                        fileNo = pqsMap.get("fileNo").toString();
                        pqsMap.put("fileNo", fileNo);
                    }
                    // 获取方案下所有任务的完成情况
                    pqsMap.put("taskAuditFlag", "N");// 是否存在待审核的任务，默认无
                    int ptsize = 0;
                    int kk = 0;

                    ptMapIn.clear();
                    if (Constants.CLOUND_SYSTEM_TYPE_FOR_OUTPATIENT.equals(systemType)) {
                        // 诊疗系统（建档或实例任务中是否有待审核的）
                        ptMapIn.put("ptSchemeId", patientSchemeId);
                        ptMapIn.put("queueId", pqsQueueId);
                        ptMapIn.put("auditStatusIn", auditStatusList);
                        List<PtArchiveTask> ptVoList = ptArchiveTaskDao.listPtArchiveTask(ptMapIn);
                        if (!CollectionUtils.isEmpty(ptVoList)) {
                            pqsMap.put("taskAuditFlag", "Y");
                        } else {
                            List<PtTrTask> ptTrTaskList = ptTrTaskDao.listTrTaskByCondition(ptMapIn);
                            if (!CollectionUtils.isEmpty(ptTrTaskList)) {
                                pqsMap.put("taskAuditFlag", "Y");
                            }
                        }
                    } else if (Constants.CLOUND_SYSTEM_TYPE_FOR_FOLLOW.equals(systemType)) {
                        // 科研随访
                        ptMapIn.put("ptSchemeId", patientSchemeId);
                        ptMapIn.put("seqNoOrderAsc", "1");
                        ptMapIn.put("taskTypeIn", taskTypeInList);
                        List<Map<String, Object>> mapOutList = patientTaskDao.selectTaskStatusByPtSchemeId(ptMapIn);
                        if (CollectionUtils.isEmpty(mapOutList) || MapUtils.isEmpty(mapOutList.get(0))) {
                            // 无任务信息，异常情况
                            ptsize = Integer.parseInt("" + pqsMap.get("totalNum"));
                            if (ptsize <= 0) {
                                pqsMap.put("taskStatusArr", "[]");
                            } else {
                                StringBuffer strStatus = new StringBuffer();
                                strStatus.append("[");
                                for (kk = 0; kk < ptsize; kk++) {
                                    strStatus.append("0,");
                                }
                                String strStr = strStatus.substring(0, strStatus.length() - 1);
                                pqsMap.put("taskStatusArr", strStr + "]");
                            }
                        } else {
                            pqsMap.put("taskStatusArr", mapOutList.get(0).get("taskStatusArr"));
                            Object scObj = (Object) mapOutList.get(0).get("auditStatusScore");
                            if (null != scObj) {
                                Integer auditStatusScore = Integer.parseInt(scObj.toString());
                                if (null != auditStatusScore && auditStatusScore > 0) {
                                    pqsMap.put("taskAuditFlag", "Y");// 存在待审核或审核未通过的任务
                                }
                            }
                        }
                    } else {
                        // 待扩展
                        // 先判断是否为科研随访
                        ptMapIn.put("ptSchemeId", patientSchemeId);
                        ptMapIn.put("seqNoOrderAsc", "1");
                        ptMapIn.put("taskTypeIn", taskTypeInList);
                        List<Map<String, Object>> mapOutList = patientTaskDao.selectTaskStatusByPtSchemeId(ptMapIn);
                        if (CollectionUtils.isEmpty(mapOutList) || MapUtils.isEmpty(mapOutList.get(0))) {
                            // 无任务信息，再判断是否为诊疗系统
                            newMapArg.clear();
                            newMapArg.put("ptSchemeId", patientSchemeId);
                            newMapArg.put("queueId", pqsQueueId);
                            List<PtArchiveTask> ptVoList = ptArchiveTaskDao.listPtArchiveTask(newMapArg);
                            if (!CollectionUtils.isEmpty(ptVoList)) {
                                newMapArg.put("auditStatusIn", auditStatusList);
                                ptVoList = ptArchiveTaskDao.listPtArchiveTask(newMapArg);
                                if (!CollectionUtils.isEmpty(ptVoList)) {
                                    pqsMap.put("taskAuditFlag", "Y");
                                } else {
                                    List<PtTrTask> ptTrTaskList = ptTrTaskDao.listTrTaskByCondition(newMapArg);
                                    if (!CollectionUtils.isEmpty(ptTrTaskList)) {
                                        pqsMap.put("taskAuditFlag", "Y");
                                    }
                                }
                            } else {
                                // 还按随访处理
                                ptsize = Integer.parseInt("" + pqsMap.get("totalNum"));
                                if (ptsize <= 0) {
                                    pqsMap.put("taskStatusArr", "[]");
                                } else {
                                    StringBuffer strStatus = new StringBuffer();
                                    strStatus.append("[");
                                    for (kk = 0; kk < ptsize; kk++) {
                                        strStatus.append("0,");
                                    }
                                    String strStr = strStatus.substring(0, strStatus.length() - 1);
                                    pqsMap.put("taskStatusArr", strStr + "]");
                                }
                            }
                        } else {
                            pqsMap.put("taskStatusArr", mapOutList.get(0).get("taskStatusArr"));
                            Object scObj = (Object) mapOutList.get(0).get("auditStatusScore");
                            if (null != scObj) {
                                Integer auditStatusScore = Integer.parseInt(scObj.toString());
                                if (null != auditStatusScore && auditStatusScore > 0) {
                                    pqsMap.put("taskAuditFlag", "Y");// 存在待审核或审核未通过的任务
                                }
                            }
                        }
                    }
                }
                StringBuffer firstNameValue = new StringBuffer();
                Iterator<String> itor = fristNameSet.iterator();
                while (itor.hasNext()) {
                    firstNameValue.append(itor.next());
                    firstNameValue.append(",");
                }
                retMap.put("FirstName", firstNameValue.substring(0, firstNameValue.length() - 1));
            }
        }
        retMap.put("total", total);
        retMap.put("rows", pqsList);

        return retMap;
    }

    /**
     * 获取高危信息登记等级
     *
     * @param patientSchemeId
     * @param pqsMap
     * @throws Exception
     */
    private void getGwSign(String patientSchemeId, Map<String, Object> pqsMap) throws Exception {
        //获取 高危信息管理 任务里面的几类高危儿 [sf_gwefl_I,sf_gwefl_II,sf_gwefl_III]
        List<String> gwList = Arrays.asList("sf_gwefl_I", "sf_gwefl_II", "sf_gwefl_III");

        HashMap<String, Object> mapCon = new HashMap<>();
        mapCon.put("taskFlag", "1");
        mapCon.put("ptSchemeId", patientSchemeId);
        List<PatientTask> patientTasks = patientTaskDao.selectByPtSchemeId(mapCon);
        List<PatientTask> archiveTask = patientTasks.stream().filter(patientTask -> patientTask.getSeqNo() == 0).collect(Collectors.toList());
        if (archiveTask.size() > 0) {
            PatientTask patientTask = archiveTask.get(0);
            mapCon.clear();
            mapCon.put("taskId", patientTask.getId());
            List<PatientContentData> contentData = patientTaskContentDAO.selectContentDataByTaskId(mapCon);
            if (contentData.size() > 0) {
                List<PatientContentData> zcejd_ch = contentData.stream().filter(item -> item.getQuestionId().equals("zcejd_ch")).collect(Collectors.toList());
                if (zcejd_ch.size() > 0) {
                    PatientContentData patientContentData = zcejd_ch.get(0);
                    pqsMap.put("bedNo", patientContentData.getQuestionAnswer());
                }

            }
        }

        List<PatientTask> taskList = patientTasks.stream().filter(patientTask -> patientTask.getTaskName().contains("高危信息管理")).collect(Collectors.toList());

        String gwSign = "";
        if (taskList.size() > 0) {
            PatientTask patientTask = taskList.get(0);
            mapCon.clear();
            mapCon.put("taskId", patientTask.getId());
            List<PatientContentData> contentData = patientTaskContentDAO.selectContentDataByTaskId(mapCon);
            if (contentData.size() > 0) {
                List<PatientContentData> collect = contentData.stream().filter(data -> gwList.contains(data.getQuestionId())).collect(Collectors.toList());
                if (collect.size() > 0) {
                    for (PatientContentData patientContentData : collect) {
                        List<String> list = Arrays.asList(patientContentData.getQuestionAnswer().replaceAll("\"", "").replace("[", "").replace("]", "").split(","));
                        if (list.size() > 0 && !list.contains("无")) {
                            if (patientContentData.getQuestionId().equals("sf_gwefl_III")) {
                                gwSign = "III类";
                                break;
                            } else if (patientContentData.getQuestionId().equals("sf_gwefl_II")) {
                                gwSign = "II类";
                                continue;
                            }
                            if (patientContentData.getQuestionId().equals("sf_gwefl_I")) {
                                gwSign = "I类";
                                continue;
                            }
                        }
                    }
                }
            }
        }
        pqsMap.put("gwSign", gwSign);
    }

    // 随访记录查询（单独封装一个组件）,modify by DemonLee 2018.3.6
    public HashMap<String, Object> listPtFollowRecord(Map<String, Object> mapIn, Jedis jedis) throws Exception {
        HashMap<String, Object> retMap = new HashMap<String, Object>();
        HashMap<String, Object> argMap = new HashMap<String, Object>(mapIn);

        String taskAgeFlag = (String) argMap.get("taskAgeFlag");
        if (null == taskAgeFlag) {
            taskAgeFlag = "";
        }
        String userStatus = (String) argMap.get("userStatus");
        String taskAuditStatus = (String) argMap.get("taskAuditStatus");
        int total = 0;
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();

        // 诊间扫码查询正常或待审核的患者或任务, modify by DemonLee 2018.03.06
        List<String> auditStatusList = new ArrayList<String>();
        List<String> userStatusList = new ArrayList<String>();
        userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
        // userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT);// 队列中待审核用户
        if (StringUtils.isBlank(userStatus)) {
            argMap.put("userStatusIn", userStatusList);
        }
        if (StringUtils.isBlank(taskAuditStatus)) {
            //
        } else {
            auditStatusList.add(taskAuditStatus);
        }
        if (!CollectionUtils.isEmpty(auditStatusList)) {
            argMap.put("auditStatusIn", auditStatusList);
        }
        argMap.put("taskStatus", Constants.PATIENT_TASK_STATUS_FINISH);// 已完成的任务
        argMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务

        if ("Y".equals(taskAgeFlag)) {
            // 安医大返回检测年龄
            total = patientQueueSchemeDao.countPatientTaskFinishAndAge(argMap);
        } else {
            total = patientQueueSchemeDao.countPatientTaskFinishInfo(argMap);
        }
        if (total > 0) {
            if ("Y".equals(taskAgeFlag)) {
                pqsList = patientQueueSchemeDao.selectPatientTaskFinishAndAge(argMap);
            } else {
                pqsList = patientQueueSchemeDao.selectPatientTaskFinishInfo(argMap);
            }
            if (null == pqsList || 0 == pqsList.size()) {
                // 数据被删除或改变了
                total = 0;
            } else {
                int pq = 0;
                String pqsQueueId = "";
                Map<String, Object> qryMapIn = new HashMap<String, Object>();
                Map<String, Object> qryMapOut = new HashMap<String, Object>();
                String finishDate = "";
                String chkAge = "-";
                for (; pq < pqsList.size(); pq++) {
                    Map<String, Object> pqsMap = pqsList.get(pq);

                    // 获取队列名称
                    pqsQueueId = (String) pqsMap.get("followQueueId");
                    qryMapIn.clear();
                    qryMapIn.put("queueId", pqsQueueId);
                    qryMapOut = getQueueName(qryMapIn, jedis);
                    pqsMap.put("followQueueName", qryMapOut.get("queueName"));

                    if (null != pqsMap.get("pregnancyDay")) {
                        pqsMap.put("pregnancyWeek",
                                ToolUtils.getPregnancyStr(Integer.parseInt("" + pqsMap.get("pregnancyDay"))));
                    } else {
                        pqsMap.put("pregnancyWeek", "-");
                    }
                    // 检测日期对应的实际年龄（配合查询入参，查询无法使用矫正年龄）
                    finishDate = (String) pqsMap.get("finishDate");
                    chkAge = "-";
                    if (null != pqsMap.get("birthday") && StringUtils.isNotBlank(finishDate)) {
                        chkAge = ToolUtils.getAgeMonDayByDate3("" + pqsMap.get("birthday"), finishDate);
                        if (StringUtils.isBlank(chkAge)) {
                            chkAge = "-";
                        }
                    }
                    pqsMap.put("chkAge", chkAge);
                }
            }
        }
        retMap.put("total", total);
        retMap.put("rows", pqsList);

        return retMap;
    }

    /**
     * 获取队列名称通用方法
     */
    public Map<String, Object> getQueueName(Map<String, Object> paramIn, Jedis jedis) throws Exception {
        Map<String, Object> paramOut = new HashMap<String, Object>();
        List<String> inList = new ArrayList<String>();

        ConfCacheUtil confCacheUtil = ConfCacheUtil.getInstance();
        String pqsQueueId = (String) paramIn.get("queueId");
        String bufferKey = "";

        // 先从内存取，取不到从redis取，redis取不到从数据库取
        if (!StringUtils.isEmpty(pqsQueueId)) {
            String cacheValue = (String) confCacheUtil.getQueueName(pqsQueueId);
            if (null == cacheValue) {
                inList.clear();
                inList.add(Constants.CONFIG_FU_QUEUE_INFO_PREFIX_QNAME);
                inList.add(pqsQueueId);
                bufferKey = ToolUtils.assembleKey(inList);
                String value1 = jedis.get(bufferKey);
                if (null == value1) {
                    Map<String, Object> queInMap = new HashMap<String, Object>();
                    queInMap.put("id", pqsQueueId);
                    List<FollowQueue> queOutList = queueDao.selectById(queInMap);
                    if (null == queOutList || 0 == queOutList.size()) {
                        throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
                    }
                    FollowQueue fqInVo = queOutList.get(0);
                    value1 = fqInVo.getQueueName();
                    jedis.set(bufferKey, value1);
                }
                confCacheUtil.setQueueName(pqsQueueId, value1);
                paramOut.put("queueName", value1);
            } else {
                paramOut.put("queueName", cacheValue);
            }
        } else {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_INPUT_DATA_VERIFY_ERROR, "队列id入参为空，无法获取队列名称！"));
        }

        return paramOut;
    }

    /**
     * 获取方案名称通用方法
     */
    public Map<String, Object> getSchemeName(Map<String, Object> paramIn, Jedis jedis) throws Exception {
        Map<String, Object> paramOut = new HashMap<String, Object>();
        List<String> inList = new ArrayList<String>();

        ConfCacheUtil confCacheUtil = ConfCacheUtil.getInstance();
        paramOut.put("schemeName", "暂无对应随访方案");
        String schemeId = (String) paramIn.get("schemeId");
        String bufferKey = "";
        if (!StringUtils.isEmpty(schemeId)) {
            // 先从内存取，取不到从redis取，redis取不到从数据库取
            String cacheValue2 = (String) confCacheUtil.getSchemeName(schemeId);
            if (null == cacheValue2) {
                if (null != schemeId && !"".equals(schemeId)) {
                    inList.clear();
                    inList.add(Constants.CONFIG_FU_SCHEME_INFO_PREFIX_SNAME);
                    inList.add(schemeId);
                    bufferKey = ToolUtils.assembleKey(inList);
                    String value2 = jedis.get(bufferKey);
                    if (null == value2) {
                        Map<String, Object> schemeInMap = new HashMap<String, Object>();
                        schemeInMap.put("id", schemeId);
                        List<FollowScheme> fsOutList = followSchemeDao.selectById(schemeInMap);
                        if (null == fsOutList || 0 == fsOutList.size()) {
                            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "未查询到对应方案信息！"));
                        }
                        FollowScheme fsmeVo = fsOutList.get(0);
                        value2 = fsmeVo.getSchemeName();
                        jedis.set(bufferKey, value2);
                    }
                    confCacheUtil.setSchemeName(schemeId, value2);
                    paramOut.put("schemeName", value2);
                }
            } else {
                paramOut.put("schemeName", cacheValue2);
            }
        }

        return paramOut;
    }

    /**
     * 获取失访原因通用方法
     */
    public Map<String, Object> getLostReason(Map<String, Object> paramIn, Jedis jedis) throws Exception {
        Map<String, Object> paramOut = new HashMap<String, Object>();
        List<String> inList = new ArrayList<String>();
        ConfCacheUtil confCacheUtil = ConfCacheUtil.getInstance();
        paramOut.put("reasonName", "");
        String reasonId = (String) paramIn.get("reasonId");
        String bufferKey = "";
        if (!StringUtils.isEmpty(reasonId)) {
            // 先从内存取，取不到从redis取，redis取不到从数据库取
            String cacheValue2 = (String) confCacheUtil.getReasonName(reasonId);
            if (null == cacheValue2) {
                if (!StringUtils.isEmpty(reasonId)) {
                    inList.clear();
                    inList.add(Constants.CONFIG_FU_LOSTREASON_PREFIX_SNAME);
                    inList.add(reasonId);
                    bufferKey = ToolUtils.assembleKey(inList);
                    String value2 = jedis.get(bufferKey);
                    if (null == value2) {
                        Map<String, Object> reasonInMap = new HashMap<String, Object>();
                        reasonInMap.put("id", reasonId);
                        List<FuLostReason> fsOutList = confCacheDao.selectLostReason(reasonInMap);
                        if (CollectionUtils.isEmpty(fsOutList)) {
                            return paramOut;
                        } else {
                            FuLostReason fsmeVo = fsOutList.get(0);
                            value2 = fsmeVo.getReasonName();
                            jedis.set(bufferKey, value2);
                        }
                    }
                    confCacheUtil.setReasonName(reasonId, value2);
                    paramOut.put("reasonName", value2);
                }
            } else {
                paramOut.put("reasonName", cacheValue2);
            }
        }

        return paramOut;
    }

    // 患者队列统计信息接口实现
    public HashMap<String, Object> qryPatientQueueStatistics(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        HashMap<String, Object> retMap = new HashMap<String, Object>();
        String authorId = (String) argMap.get("authorId");
        String tenantId = (String) argMap.get("tenantId");
        Integer schemeBusiType = (Integer) argMap.get("schemeBusiType");

        String windowPtTotal = "0";
        String windowPtFinish = "0";
        String windowPtGoing = "0";
        String ptLostToday = "0";
        String followPtTotal = "0";

        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.select(Constants.REDIS_DB_INDEX_PATIENT);

            // 今日建档患者数量（暂时取当前账号下的数据）
            Map<String, Object> redisOut = ptQueueRedis.getPatientAddByAuthorId(authorId, jedis);
            String ptAddToday = (String) redisOut.get(Constants.REDIS_DATA_DAY);
            if (null == ptAddToday) {
                // redis无数据，则查询物理库？
                ptAddToday = "0";
            }
            int ptAddTodayInt = patientDao.selectTotalDayCreate(argMap);
            //if(ptAddTodayInt!=0) {
            retMap.put("dayIncrPtNum", ptAddTodayInt + "");
            /*}else {
            	retMap.put("dayIncrPtNum", ptAddToday);
            }*/

            // 今日门诊患者数量
            redisOut.clear();
            redisOut = ptQueueRedis.getPatientDoorByAuthorId(authorId, jedis);
            String ptDoorToday = (String) redisOut.get(Constants.REDIS_DATA_DAY);
            if (null == ptDoorToday) {
                ptDoorToday = "0";
            }
            retMap.put("dayIncrDoorNum", ptDoorToday);

            Map<String, Object> qryQueueMap = new HashMap<String, Object>();
            qryQueueMap.put("authorId", authorId);
            qryQueueMap.put("queueStatus", Constants.QUEUE_STATUS_NOMAL);// 队列状态正常
            qryQueueMap.put("tenantId", tenantId);
            qryQueueMap.put("queueTypePrivate", Constants.QUEUE_TYPE_PRIVATE);
            qryQueueMap.put("queueTypeTenant", Constants.QUEUE_TYPE_TENANT);
            qryQueueMap.put("queueTypePublic", Constants.QUEUE_TYPE_PUBLIC);
            List<FollowQueue> fqList = queueDao.selectQueueIdByAuthority(qryQueueMap);
            if (ObjectUtil.isNotEmpty(fqList)) {
                List<String> queueIds = followQueueAuthorityDAO.getDuiLieByAuthorId(authorId);
                fqList = fqList.stream().filter(item -> {
                    if (queueIds.contains(item.getId())) {
                        return true;
                    } else {
                        return false;
                    }
                }).collect(Collectors.toList());
            }

            if (null != fqList && 0 != fqList.size()) {
                // 根据当前登录账号获取，其可以查看的队列id（权限处理比较复杂，这里先简化）
                List<String> queueIdArray = new ArrayList<String>();
                int fqt = 0;
                for (; fqt < fqList.size(); fqt++) {
                    FollowQueue fqVo = fqList.get(fqt);
                    // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                    queueIdArray.add(fqVo.getId());
                }

                Map<String, Object> cntPtQueueMap = new HashMap<String, Object>();
                if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType || Constants.SCHEME_BUSI_TYPE_2 == schemeBusiType) {
                    cntPtQueueMap.put("totalNumNonZero", "1");
                }
                cntPtQueueMap.put("queueIdIn", queueIdArray);
                cntPtQueueMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
                int iptTotalNum = patientQueueSchemeDao.countTotalPtQueueNumByTaskNum(cntPtQueueMap);
                followPtTotal = "" + iptTotalNum;

                if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType) {
                    //查询门诊人数
                    int dayIncrDoorNum = patientQueueSchemeDao.countTotalPtQueueNumByQueueId(cntPtQueueMap);
                    retMap.put("dayIncrDoorNum", dayIncrDoorNum + "");
                }
                if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType || Constants.SCHEME_BUSI_TYPE_2 == schemeBusiType) {
                    // 今日失访数量（即统计昨天为窗口期的患者）
                    redisOut.clear();
                    // redisOut =
                    // ptQueueRedis.getPatientLostByAuthorId(authorId,
                    // jedis);
                    ptLostToday = (String) redisOut.get(Constants.REDIS_DATA_DAY);
                    if (null == ptLostToday) {
                        // redis暂时没有，从物理库获取
                        Map<String, Object> qryPtMap = new HashMap<String, Object>();
                        qryPtMap.put("queueIdIn", queueIdArray);
                        qryPtMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
                        qryPtMap.put("endExpiredTime", DateUtil.getCurrDateByDay(1, Constants.SUBTRACT_CHAR));// 截止时间=昨天
                        qryPtMap.put("taskExistsFlag", "1");
                        qryPtMap.put("reverseTaskStatus", Constants.PATIENT_TASK_STATUS_FINISH);// 去掉已完成的任务
                        qryPtMap.put("tenantId", tenantId);
                        qryPtMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
                        int ptLostNum = patientQueueSchemeDao.countTotalPtQueueNumByCondition(qryPtMap);
                        ptLostToday = "" + ptLostNum;
                    }

                    // 随访期患者总数，已完成数，进行中数
                    redisOut.clear();
                    // redisOut =
                    // ptQueueRedis.getWindowPtTotalByAuthorId(authorId,
                    // jedis);
                    windowPtTotal = (String) redisOut.get(Constants.REDIS_DATA_TOTAL);
                    windowPtFinish = "0";
                    windowPtGoing = "0";
                    // redis暂时没有，从物理库获取
                    if (null == windowPtTotal) {
                        Map<String, Object> qryPtMap = new HashMap<String, Object>();
                        qryPtMap.put("queueIdIn", queueIdArray);
                        qryPtMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
                        qryPtMap.put("endTime", DateUtil.getCurrDate());// 截止时间>=当前时间
                        qryPtMap.put("beginTime", DateUtil.getCurrDate());// 开始时间<=当前时间
                        if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType
                                || Constants.SCHEME_BUSI_TYPE_2 == schemeBusiType) {
                            qryPtMap.put("taskExistsFlag", "1");
                        }
                        qryPtMap.put("tenantId", tenantId);
                        qryPtMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
                        // 总人数
                        qryPtMap.put("reverseTaskStatus", Constants.PATIENT_TASK_STATUS_EXPIRED);// 去掉已过期的任务
                        qryPtMap.put("initTaskRev", "1");// 建档任务不算在窗口期内
                        int winTotalNum = patientQueueSchemeDao.countTotalPtQueueNumByCondition(qryPtMap);
                        // 进行中人数
                        qryPtMap.put("reverseTaskStatus", null);
                        qryPtMap.put("taskStatus", Constants.PATIENT_TASK_STATUS_INIT);// 未开始的任务
                        int winGoingNum = patientQueueSchemeDao.countTotalPtQueueNumByCondition(qryPtMap);
                        // 已完成人数
                        int winFinishNum = winTotalNum - winGoingNum;
                        if (Constants.SCHEME_BUSI_TYPE_1 == schemeBusiType) {
                            // 诊疗无
                            winGoingNum = 0;
                            winFinishNum = 0;
                        }

                        windowPtTotal = "" + winTotalNum;
                        windowPtGoing = "" + winGoingNum;
                        windowPtFinish = "" + winFinishNum;
                    }
                }
            } else {
                logger.warn("该账号无可查看到的队列信息...arg==" + qryQueueMap.toString());
                windowPtTotal = "0";
                windowPtFinish = "0";
                windowPtGoing = "0";
                ptLostToday = "0";
                followPtTotal = "0";
            }
        } catch (JedisConnectionException jex) {
            logger.error("redis连接异常..." + jex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
        } finally {
            if (null != jedis) {
                try {
                    jedis.close();
                    logger.warn("close redis connection...");
                } catch (Exception ex) {
                    ex.printStackTrace();
                    throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_CLOSE_FAILED,
                            "Redis缓存关闭失败!"));
                }
            }
        }
        retMap.put("followPtTotal", followPtTotal);
        retMap.put("dayLostNum", ptLostToday);
        retMap.put("windowPtTotal", windowPtTotal);
        retMap.put("windowPtGoing", windowPtGoing);
        retMap.put("windowPtFinish", windowPtFinish);

        return retMap;
    }

    // 患者所在队列的任务列表接口实现
    public List<Object> qryPatientTaskList(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        // 查询任务类型为：门诊任务+线上随访（暂时）
        List<String> typeList = new ArrayList<String>();
        typeList.add(Constants.TASK_TYPE_SCHEME_SCHEDULE);// 只展示门诊任务
        // typeList.add(Constants.TASK_TYPE_SCHEME_TEMP);
        argMap.put("taskTypeCreate", typeList);
        argMap.put("seqNoCreate", Constants.TASK_SEQ_FOR_INIT);// 需要展示建档任务(可能是非门诊任务）
        List<PatientTask> ptList = patientTaskDao.selectByPtSchemeId(argMap);
        List<Object> retList = new ArrayList<Object>();
        int seqNo = -1;
        if (null != argMap.get("seqNo")) {
            seqNo = Integer.parseInt("" + argMap.get("seqNo"));
        }
        String tempTaskFlag, finishDate, executeTime;
        if (null != ptList && 0 != ptList.size()) {
            int ipt = 0;
            int chkFlag = 0;
            for (; ipt < ptList.size(); ipt++) {
                HashMap<String, Object> ptMap = new HashMap<String, Object>();
                boolean taskFlag = false;
                PatientTask ptask = ptList.get(ipt);
                tempTaskFlag = ptask.getTemporaryTask();
                finishDate = ptask.getFinishDate();
                executeTime = ptask.getExecuteTime();
                ptMap.put("queueName", ptask.getQueueName());
                ptMap.put("id", ptask.getId());
                ptMap.put("taskId", ptask.getId());
                ptMap.put("userId", ptask.getUserId());
                ptMap.put("ptSchemeId", ptask.getPtSchemeid());
                ptMap.put("taskName", ptask.getTaskName());
                ptMap.put("taskWindowDay", ptask.getWindowDay());
                ptMap.put("taskDate", ptask.getExecuteTime());
                ptMap.put("seqNo", ptask.getSeqNo());
                ptMap.put("executeType", ptask.getExecuteType());
                ptMap.put("informFlag", ptask.getInformFlag());
                ptMap.put("followQueueId", ptask.getQueueId());
                ptMap.put("taskStatus", ptask.getTaskStatus());
                ptMap.put("auditStatus", ptask.getAuditStatus());
                ptMap.put("warnDay", ptask.getWarnDay());
                ptMap.put("executeDay", ptask.getExecuteDay());
                ptMap.put("updateTime", ptask.getUpdateTime());
                ptMap.put("createTime", ptask.getCreateTime());
                ptMap.put("executeTime", executeTime);
                ptMap.put("beginTime", ptask.getBeginTime());
                ptMap.put("endTime", ptask.getEndTime());
                ptMap.put("queueId", ptask.getQueueId());
                ptMap.put("updateAccept", ptask.getUpdateAccept());
                ptMap.put("taskType", ptask.getTaskType());
                ptMap.put("smsNum", ptask.getSmsNum());
                if (!StringUtils.isEmpty(tempTaskFlag) && tempTaskFlag.equals("1")) {
                    //临时随访。
                    ptMap.put("finishDate", StringUtils.isEmpty(finishDate) ? executeTime : finishDate);
                } else {
                    //计划随访。
                    ptMap.put("finishDate", finishDate == null ? "" : finishDate);
                }
                ptMap.put("finishTime", ptask.getFinishTime());
                ptMap.put("updateAuname", ptask.getUpdateAuname());
                ptMap.put("nextDate", ptask.getNextDate());
                ptMap.put("tempTask", tempTaskFlag == null ? "" : tempTaskFlag);  //临时随访标记。

                String nowDate = DateUtil.getCurrDate();
                String beginTime = DateUtil.getTimeString(ptask.getBeginTime());
                String endTime = DateUtil.getTimeString(ptask.getEndTime());
                // 若传了seqNo，则以seqNo对应任务为默认展示
                if (-1 != seqNo) {
                    if (seqNo == ptask.getSeqNo()) {
                        taskFlag = true;
                        chkFlag = 1;
                    }
                } else {
                    // 当天在哪次任务的时间窗口期内
                    if (Constants.TASK_SEQ_FOR_INIT == ptask.getSeqNo()) {
                        taskFlag = false;// 建档暂时只可读，不算在窗口期内
                    } else if (nowDate.compareTo(beginTime) >= 0 && nowDate.compareTo(endTime) <= 0) {
                        taskFlag = true;
                        chkFlag = 1;
                    }
                }
                ptMap.put("currentTaskFlag", taskFlag);
                retList.add(ptMap);
            }
            if (0 == chkFlag) {
                // 如果所有任务都未选中展示，则默认展示最后一次
                int retsize = retList.size();
                if (0 != retsize) {
                    HashMap<String, Object> ptMap = ToolUtils.typeCast(retList.get(retsize - 1));
                    ptMap.put("currentTaskFlag", true);
                }
            }
        }

        Collections.sort(retList, new TaskComparator());    //重新排序这些随访任务。

        return retList;
    }

    @Override
    public HashMap<String, Object> pageList(HashMap<String, Object> paramMap) {
        HashMap<String, Object> retMap = new HashMap<String, Object>();

        // 获取队列名称
        try {
            List<FuClosecaseRecordVo> records = fuClosecaseRecordDao.pageList(paramMap);
            for (int i = 0; i < records.size(); i++) {
                FuClosecaseRecordVo vo = records.get(i);
                HashMap hashMap = new HashMap();
                hashMap.put("userId", vo.getUserId());
                Patient patient = this.getPatient(hashMap);
                if (null != patient.getExpectedDay() && !patient.getExpectedDay().equals("")) {
                    vo.setExpectedDay(patient.getExpectedDay());
                }
                vo.setPregnancyDay(patient.getPregnancyDay());
                paramMap.put("currDate", DateUtil.getCurrDate());
                paramMap.put("ptSchemeId", vo.getPtSchemeid());
                List<PatientTask> ptList = patientTaskDao.selectByPtSchemeId(paramMap);
                if (null != ptList && ptList.size() > 0) {
                    for (int j = 0; j < ptList.size(); j++) {
                        PatientTask task = ptList.get(j);
                        if (task.getPtSchemeid().equals(vo.getPtSchemeid()) && task.getId().equals(vo.getTaskId())) {
                            vo.setQueueName(task.getQueueName());
                            vo.setTaskName(task.getTaskName());
                        }
                    }
                } else {
                    System.out.println("error");
                }
            }
            retMap.put("total", fuClosecaseRecordDao.pageListCount(0, 0));
            retMap.put("rows", records);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retMap;

    }

    // 获取模板内容通用接口实现
    public Map<String, Object> getContTemplData(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        HashMap<String, Object> contVerMap = new HashMap<String, Object>();

        // 后续从redis缓存获取，这里先从物理库中获取
        contVerMap.put("id", paramIn.get("templVersionId"));
        List<ContentTemplVersion> ctvList = contentTemplDao.selectContentTemplById(contVerMap);
        // System.out.println("111111111111" + ctvList.toString());
        if (null == ctvList || 0 == ctvList.size()) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST, "未查询到任务内容模板记录！");
        }
        ContentTemplVersion ctv = ctvList.get(0);

        String templDataStr = ctv.getTemplData();
        if (StringUtils.isBlank(templDataStr)) {
            // throw new
            // AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_IS_NULL,
            // "任务内容模板值为空！");
            return outMap;
        }

        // 数据库默认配置为json数组格式
        JSONArray templJsonArray = null;
        try {
            templJsonArray = JSON.parseArray(templDataStr);
            outMap.put("contData", templJsonArray);
        } catch (JSONException arex) {
            logger.error("任务内容模板格式配置错误，非json数组格式： " + arex.getMessage());

            // 非json数组格式，则按json格式再解析
            JSONObject templJsonObject = null;
            try {
                templJsonObject = JSON.parseObject(templDataStr);
                outMap.put("contData", templJsonObject);
            } catch (JSONException exobj) {
                exobj.printStackTrace();
                // 后续重写异常类
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_CONFIG_IRREGULAR,
                        "问卷模板配置错误，非json格式！"));
            }
        } catch (AppException appex) {
            throw (appex);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_CONFIG_IRREGULAR,
                    "问卷模板格式解析错误：" + ex.getMessage());
        }

        return outMap;
    }

    @Override
    public PhysiqueInfo getPhysiqueInfo(String taskId) throws Exception {
        List<PatientTask> ptVoList = patientTaskDao.selectByTaskId(taskId);
        PatientTask ptTaskVo = ptVoList.get(0);
        if (Constants.TASK_SEQ_FOR_INIT == ptTaskVo.getSeqNo()) {
            return null;
        }

        Map<String, Object> inMap = new HashMap<>();
        inMap.put("userId", ptTaskVo.getUserId());
        inMap.put("ptSchemeId", ptTaskVo.getPtSchemeid());
        inMap.put("seqNo", Constants.TASK_SEQ_FOR_INIT);
        List<PatientTask> taskList = patientTaskDao.select(inMap);
        PatientTask ptTask = taskList.get(0);
        inMap.put("taskId", ptTask.getId());
        List<PatientContentData> patientContentData = patientTaskConDao.selectContentDataByTaskId(inMap);
        PhysiqueInfo physiqueInfo = new PhysiqueInfo();
        patientContentData.forEach(item -> {
            if (item.getQuestionId().equals("Height")) {
                physiqueInfo.setHeight(item.getQuestionAnswer());
            }
            if (item.getQuestionId().equals("Weight")) {
                physiqueInfo.setWeight(item.getQuestionAnswer());
            }
        });
        if (StringUtils.isNotEmpty(physiqueInfo.getHeight()) && StringUtils.isNotEmpty(physiqueInfo.getWeight())) {
            Double bodyMassIndex = Double.parseDouble(physiqueInfo.getWeight()) / ((Double.parseDouble(physiqueInfo.getHeight())/100)*(Double.parseDouble(physiqueInfo.getHeight())/100));
            physiqueInfo.setBodyMassIndex(bodyMassIndex);
        }
        return physiqueInfo;
    }

    // 患者任务内容列表查询接口实现
    public HashMap<String, Object> qryPatientContentList(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        HashMap<String, Object> retOutMap = new HashMap<String, Object>();

        // 权限信息
        // String authorName = (String) argMap.get("authorName");
        // String authorId = (String) argMap.get("authorId");
        String tenantId = (String) argMap.get("tenantId");
        int groupType = (Integer) argMap.get("groupType");
        String rootGroupId = (String) argMap.get("rootGroupId");


        String taskId = (String) argMap.get("taskId");
        String queueId = (String) argMap.get("queueId");
        List<PatientTask> ptVoList = patientTaskDao.selectById(argMap);
        if (null == ptVoList || 0 == ptVoList.size()) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASK_NOT_EXIST, "该患者当前任务不存在！");
        }
        PatientTask ptTaskVo = ptVoList.get(0);
        if (Constants.TASK_SEQ_FOR_INIT == ptTaskVo.getSeqNo()) {
            // 建档任务需要将基本信息返回
            Map<String, Object> userMap = new HashMap<String, Object>();
            userMap.put("userId", ptTaskVo.getUserId());
            //TODO by jiangq on 2022年09月28日 转诊功能增加，主中心查询分中心患者不带租户id，用户id唯一，暂时这样处理。
            if (argMap.containsKey("refTenantId") && StringUtils.isNotBlank((String) argMap.get("refTenantId"))) {
                userMap.put("tenantId", tenantId);
            }
            Patient ptVo = patientDao.selectById(userMap);
            if (null == ptVo) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
            }
            retOutMap.put("patientInfo", ptVo);

            // 患者扩展信息
            Map<String, Object> outExtMap = new HashMap<String, Object>();
            Map<String, Object> ptExtMap = new HashMap<String, Object>();
            ptExtMap.put("userId", ptVo.getId());
            List<PtUserextendInfo> ptextList = ptExtendDao.selectPtExtendInfo(ptExtMap);
            if (null != ptextList && 0 != ptextList.size()) {
                int iextNum = ptextList.size();
                int kk = 0;
                for (kk = 0; kk < iextNum; kk++) {
                    PtUserextendInfo pextVo = ptextList.get(kk);
                    outExtMap.put(pextVo.getParamName(), pextVo.getParamValue());
                }
            }
            retOutMap.put("extendInfo", outExtMap);
        }

        List<Object> conDataList = new ArrayList<Object>();
        List<Object> contentIdList = new ArrayList<Object>();
        List<PatientTaskContent> ptcList = patientTaskConDao.selectContentByTaskId(argMap);
        if (!CollectionUtils.isEmpty(ptcList)) {
            // questiones
            int ipt = 0;
            int isize = ptcList.size();
            Map<String, Object> templMap = new HashMap<String, Object>();
            Map<String, Object> equalMap = new HashMap<String, Object>();
            // 找出模板内容相同的问卷
            for (ipt = 0; ipt < isize; ipt++) {
                PatientTaskContent ptaskc = ptcList.get(ipt);
                String templType = ptaskc.getTemplType();
                String templVersionId = ptaskc.getTemplVersionid();
                if (Constants.QUESTIONNAIRE_TYPE_0.equals(templType)) {
                    templMap.put("id", templVersionId);
                    List<ContentTemplVersion> ctvList = contentTemplDao.selectContentTemplNoTextById(templMap);
                    if (null == ctvList || 0 == ctvList.size()) {
                        continue;
                    }
                    String equalId = ctvList.get(0).getEqualId();
                    if (!StringUtils.isEmpty(equalId)) {
                        equalMap.put(equalId, templVersionId);
                    }
                }
            }
            logger.warn("equalMap==" + equalMap.toString());

            // 剔除相同内容的非门诊问卷
            boolean eraseFlag = false;
            Map<String, Object> dataOut = new HashMap<String, Object>();
            Map<String, Object> contVerMap = new HashMap<String, Object>();
            for (ipt = 0; ipt < isize; ipt++) {
                PatientTaskContent ptaskc = ptcList.get(ipt);
                Map<String, Object> ptcInMap = new HashMap<String, Object>();
                String templType = ptaskc.getTemplType();
                String templVersionId = ptaskc.getTemplVersionid();
                if (!Constants.QUESTIONNAIRE_TYPE_0.equals(templType)) {
                    if (null != equalMap.get(templVersionId)) {
                        // 该问卷与门诊问卷内容相同，需要剔除
                        logger.warn("erase templVersionId==" + templVersionId);
                        eraseFlag = true;
                        continue;
                    }
                }
                ptcInMap.put("templType", templType);
                ptcInMap.put("contentId", ptaskc.getId());
                contentIdList.add(ptcInMap);

                // 获取内容模板
                contVerMap.clear();
                contVerMap.put("templVersionId", templVersionId);
                dataOut = getContTemplData(contVerMap);
                if (null != dataOut.get("contData")) {
                    conDataList.add(dataOut.get("contData"));
                }
            }
            retOutMap.put("questiones", conDataList);

            // values
            HashMap<String, Object> questionMap = new HashMap<String, Object>();
            List<PatientContentData> ptTaskConList;
            if (!eraseFlag) {
                // 没有重复问卷，优先查门诊答案，没有门诊答案，则查询所有答案
                Map<String, Object> valMapIn = new HashMap<String, Object>();
                valMapIn.put("taskId", taskId);
                valMapIn.put("contDataTemplType", Constants.QUESTIONNAIRE_TYPE_0);
                ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                if (!CollectionUtils.isEmpty(ptTaskConList)) {
                    int k = 0;
                    for (; k < ptTaskConList.size(); k++) {
                        PatientContentData pcdVo = ptTaskConList.get(k);
                        questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                        //Edit by jiangq on 2023年09月19日 多级题型处理
                        if (pcdVo.getQuestionId().contains("rowNumber")) {
                            dealMultiLevel(retOutMap, pcdVo);
                        }
                    }
                } else {
                    valMapIn.put("contDataTemplType", null);
                    ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                    if (!CollectionUtils.isEmpty(ptTaskConList)) {
                        int k = 0;
                        for (; k < ptTaskConList.size(); k++) {
                            PatientContentData pcdVo = ptTaskConList.get(k);
                            questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                        }
                    }
                }
            } else {
                // 有重复的问卷，则需要考虑两种情况：
                // 1、门诊问卷已有答案，则使用自己的答案
                // 2、门诊问卷没有答案，则使用关联问卷的答案
                Map<String, Object> valMapIn = new HashMap<String, Object>();
                valMapIn.put("taskId", taskId);
                valMapIn.put("contDataTemplType", Constants.QUESTIONNAIRE_TYPE_0);
                ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                if (!CollectionUtils.isEmpty(ptTaskConList)) {
                    int k = 0;
                    for (; k < ptTaskConList.size(); k++) {
                        PatientContentData pcdVo = ptTaskConList.get(k);
                        questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                    }
                } else {
                    valMapIn.clear();
                    valMapIn.put("taskId", taskId);
                    ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                    if (!CollectionUtils.isEmpty(ptTaskConList)) {
                        int k = 0;
                        for (; k < ptTaskConList.size(); k++) {
                            PatientContentData pcdVo = ptTaskConList.get(k);
                            questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                        }
                    }
                }
            }
            retOutMap.put("values", questionMap);
            retOutMap.put("PtContentdataInfo", ptTaskConList);
        }

        // task
        Map<String, Object> taskMap = new HashMap<String, Object>();
        taskMap.put("ptTaskId", taskId);
        taskMap.put("ptContentIds", contentIdList);
        taskMap.put("ptTaskName", ptTaskVo.getTaskName());
        taskMap.put("taskNote", ptTaskVo.getTaskNote());
        taskMap.put("updateAuname", ptTaskVo.getUpdateAuname());
        taskMap.put("seqNo", ptTaskVo.getSeqNo());
        taskMap.put("taskStatus", ptTaskVo.getTaskStatus());// 任务状态
        taskMap.put("taskDate", ptTaskVo.getExecuteTime());// 任务计划执行日期
        // 随访日期和完成时间不是同一天时，已随访日期为准
        String finishTime = ptTaskVo.getFinishTime();
        String finishDate = ptTaskVo.getFinishDate();

        if (finishDate == null) {
            if (!StringUtils.isEmpty(ptTaskVo.getTemporaryTask()) && ptTaskVo.getTemporaryTask().equals("1")) {
                //临时随访。
                taskMap.put("finishDate", ptTaskVo.getExecuteTime());
            } else {
                taskMap.put("finishDate", "");
            }
        } else {
            taskMap.put("finishDate", finishDate);
        }

        String finishTimeSplit = "";
        if (StringUtils.isBlank(finishTime)) {
            finishTime = finishDate;
        } else {
            finishTimeSplit = DateUtil.getTimeStampDay(finishTime);
            if (StringUtils.isNotBlank(finishDate) && !finishDate.equals(finishTimeSplit)) {
                finishTime = finishDate;
            }
        }
        if (finishTime == null) {
            //taskMap.put("finishTime", "");
        } else {
            taskMap.put("finishTime", finishTime);
        }


        // 校验权限（暂只支持科室排班，后续扩展）
        String deptId = "";
        if (Constants.TENANT_GROUP_TYPE_FOR_DEPT == groupType) {
            // 科室排班
            deptId = rootGroupId;
        } else if (Constants.TENANT_GROUP_TYPE_FOR_HOSPITAL == groupType) {
            // 医院排班
        } else if (Constants.TENANT_GROUP_TYPE_FOR_MULCENTER == groupType) {
            // 多中心排班
        } else if (Constants.TENANT_GROUP_TYPE_FOR_UNION == groupType) {
            // 医联体排班
        } else {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TENANT_TYPE_UNKNOWN, "暂无匹配的租户类型，无法查询门诊地址!"));
        }

        // 随访指导（下次随访地点和随访时间）
        List<String> addressList = new ArrayList<String>();
        Map<String, Object> deptConMap = new HashMap<String, Object>();
        deptConMap.put("deptId", deptId);
        String nextAddress = ptTaskVo.getNextAddress();
        if (!StringUtils.isEmpty(nextAddress)) {
            deptConMap.put("revAddress", nextAddress);
            // 将已填写过的下次随访地址放在第一选项
            addressList.add(nextAddress);
        }
        List<Contact> dcList = deptContactDao.listDeptContactByCondition(deptConMap);
        if (!CollectionUtils.isEmpty(dcList)) {
            int kt = 0;
            int dcsize = dcList.size();
            Contact ct = new Contact();
            for (kt = 0; kt < dcsize; kt++) {
                ct = dcList.get(kt);
                addressList.add(ct.getAddress());
            }
        }
        taskMap.put("nextAddress", addressList);

        Map<String, String> nextDateMap = new HashMap<String, String>();
        List<String> nextDateList = new ArrayList<String>();
        String nextDate = ptTaskVo.getNextDate();
        if (!StringUtils.isEmpty(nextDate)) {
            // 将已填写过的下次随访日期放在第一选项
            String nextDateTime = "";
            if (-1 != nextDate.indexOf(Constants.COLON_SPLIT_STR)) {
                String[] nextDateArr = nextDate.split(Constants.COLON_SPLIT_STR);
                nextDateTime = nextDateArr[0];
            } else {
                nextDateTime = nextDate;
            }
            nextDateList.add(nextDateTime);
            nextDateMap.put(nextDateTime, "1");
            taskMap.put("nextDateTime", nextDateTime);
        }
        // 根据科室id获取科室排班
        Map<String, Object> randSchedule = new HashMap<String, Object>();
        randSchedule.put("deptId", rootGroupId);
        List<RandOutPatientSchedule> ropsList = outPatientScheduleDao.listRandOutPatientScheduleByDept(randSchedule);
        if (!CollectionUtils.isEmpty(ropsList)) {
            List<Map<String, Object>> scheduleList = new ArrayList<Map<String, Object>>();
            int kt = 0;
            int dcsize = ropsList.size();
            RandOutPatientSchedule rtVo = new RandOutPatientSchedule();
            for (kt = 0; kt < dcsize; kt++) {
                Map<String, Object> rpMap = new HashMap<String, Object>();
                rtVo = ropsList.get(kt);
                rpMap.put("workDay", rtVo.getWorkDay());
                rpMap.put("workPeriod", rtVo.getWorkPeriod());
                scheduleList.add(rpMap);
            }

            // 查询下次task信息
            Map<String, Object> nextMap = new HashMap<String, Object>();
            nextMap.put("ptSchemeId", ptTaskVo.getPtSchemeid());
            nextMap.put("seqNo", ptTaskVo.getSeqNo() + 1);
            nextMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
            List<PatientTask> nextTaskList = patientTaskDao.select(nextMap);
            if (!CollectionUtils.isEmpty(nextTaskList)) {
                PatientTask nextPtTaskVo = nextTaskList.get(0);
                Map<String, Object> calcMap = new HashMap<String, Object>();
                calcMap.put("scheduleType", ropsList.get(0).getScheduleType());// 一个科室只有一种类型的排班
                calcMap.put("scheduleList", scheduleList);
                calcMap.put("beginTime", nextPtTaskVo.getBeginTime());
                calcMap.put("endTime", nextPtTaskVo.getEndTime());
                calcMap.put("executeTime", nextPtTaskVo.getExecuteTime());
                // 计算下次门诊的时间
                List<String> nextList = ToolUtils.calcNextDate(calcMap);
                if (!CollectionUtils.isEmpty(nextList)) {
                    dcsize = nextList.size();
                    String nextTime = "";
                    for (kt = 0; kt < dcsize; kt++) {
                        nextTime = nextList.get(kt);
                        if (!StringUtils.isEmpty(nextDate) && nextDate.equals(nextTime)) {
                            continue;
                        } else {
                            String nextDateTime = "";
                            if (-1 != nextTime.indexOf(Constants.COLON_SPLIT_STR)) {
                                String[] nextDateArr = nextTime.split(Constants.COLON_SPLIT_STR);
                                nextDateTime = nextDateArr[0];
                            } else {
                                nextDateTime = nextTime;
                            }
                            // 剔除重复
                            if (null == nextDateMap.get(nextDateTime)) {
                                nextDateList.add(nextDateTime);
                                nextDateMap.put(nextDateTime, "1");
                            }
                        }
                    }
                }
            }
        }
        taskMap.put("nextDate", nextDateList);

        // 生物样本收集（安医大需求）
        Map<String, Object> sampleMapIn = new HashMap<String, Object>();
        sampleMapIn.put("userId", ptTaskVo.getUserId());
        sampleMapIn.put("ptSchemeId", ptTaskVo.getPtSchemeid());
        sampleMapIn.put("tenantId", tenantId);
        List<Map<String, Object>> sampleList = this.listSampleInfo(sampleMapIn);
        if (!CollectionUtils.isEmpty(sampleList)) {
            retOutMap.put("sampleList", sampleList);
        }

        retOutMap.put("task", taskMap);

        // opr_info
        HashMap<String, Object> oprInfoMap = new HashMap<String, Object>();
        oprInfoMap.put("patientId", ptTaskVo.getUserId());
        oprInfoMap.put("ptSchemeId", ptTaskVo.getPtSchemeid());
        oprInfoMap.put("followQueueId", queueId);
        retOutMap.put("oprInfo", oprInfoMap);
        retOutMap.put("PtTaskcontentInfo", ptcList);

        return retOutMap;
    }

    /**
     * Edit by jiangq on 2023年09月19日
     * 多级题型处理
     */
    private void dealMultiLevel(HashMap<String, Object> retOutMap, PatientContentData patientContentData) throws Exception {
        //拿到第几次的记录
        System.out.println(patientContentData.getQuestionId());

        String rowNumber = patientContentData.getQuestionId().substring(patientContentData.getQuestionId().lastIndexOf("_") + 1);
        List<Object> questiones = (List<Object>) retOutMap.get("questiones");
        JSONArray questioneTemp = null;
        String oldRowNumber = null;
        boolean flag = false;
        for (Object questione : questiones) {
            JSONArray questioneMap = (JSONArray) questione;
            for (Object o : questioneMap) {
                JSONObject questioneMapObj = (JSONObject) o;
                JSONObject questioneMapTemp = JSON.parseObject(String.valueOf(questioneMapObj));
                String oldLable = (String) questioneMapTemp.get("label");
                oldRowNumber = oldLable.substring(oldLable.lastIndexOf("_") + 1);
                if (rowNumber.equals(oldRowNumber)) {
                    break;
                }
                questioneTemp = JSON.parseArray(String.valueOf(questioneMap));
                String label = (oldLable.substring(0, oldLable.lastIndexOf("_") + 1)) + rowNumber;
                //验证questiones里面是否有当前的添加次数，如果有，则踢出
                flag = filterQuestion(questiones, label);
                if (flag) break;
                System.out.println(label);

                questioneMapTemp.put("label", label);

                JSONArray childrens = (JSONArray) questioneMapTemp.get("children");
                JSONArray childArray = JSON.parseArray(String.valueOf(childrens));
                if (null != questioneMapTemp.get("type") && questioneMapTemp.get("type").equals("qusetion_groupMore")) {
                    for (Object children : childArray) {
                        JSONObject childrenMap = (JSONObject) children;
                        Object qid = childrenMap.get("id");

                        if (null != qid && qid instanceof String) {
                            String id = (String) childrenMap.get("id");
                            childrenMap.put("id", (id.substring(0, id.lastIndexOf("_") + 1)) + rowNumber);
                        } else if (null != qid && qid instanceof JSONArray) {
                            JSONArray jsonArray = (JSONArray) childrenMap.get("id");
                            JSONArray queJonsArray = new JSONArray();
                            for (Object id : jsonArray) {
                                String tempId = (String) id;
                                queJonsArray.add((tempId.substring(0, tempId.lastIndexOf("_") + 1)) + rowNumber);
                            }
                            childrenMap.put("id", queJonsArray);
                        }
                    }
                    questioneMapTemp.put("children", childArray);
                }
                questioneTemp.clear();
                questioneTemp.add(questioneMapTemp);
            }
        }


        if (!flag && null != questioneTemp) {
            questiones.add(questioneTemp);
        }
        Collections.sort(questiones, new QuestionsComparator());    //重新排序这些问题。

        retOutMap.put("questiones", questiones);
    }

    /**
     * Edit by jiangq on 2023年09月20日
     * 过滤已经加过的问卷
     *
     * @param questiones
     * @param label
     * @return
     */
    private boolean filterQuestion(List<Object> questiones, String label) {
        boolean flag = false;
        for (Object questione : questiones) {
            JSONArray questioneMap = (JSONArray) questione;
            for (Object o : questioneMap) {
                JSONObject questioneMapObj = (JSONObject) o;
                JSONObject questioneMapTemp = JSON.parseObject(String.valueOf(questioneMapObj));
                if (questioneMapTemp.get("label").toString().equals(label)) {
                    flag = true;
                    break;
                }

            }
        }
        return flag;
    }

    /**
     * 生长发育题型需要将数据入表
     */
    public Map<String, Object> dealGrowthDevApi(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramIn);
        JSONObject jsonMap = new JSONObject(paramIn);
        Map<String, Object> quesMap = (JSONObject) jsonMap.getJSONObject("contentData");
        if (!MapUtils.isEmpty(quesMap)) {
            // 身高
            String weight = (String) quesMap.get(Constants.QUESTION_ID_FOR_GROWTHDEV_WEIGHT);
            // 体重
            String height = (String) quesMap.get(Constants.QUESTION_ID_FOR_GROWTHDEV_HEIGHT);
            // 头围
            String headCircumference = (String) quesMap.get(Constants.QUESTION_ID_FOR_GROWTHDEV_HEADCIRCUM);

            String userId = (String) argMap.get("userId");
            if (StringUtils.isEmpty(userId)) {
                return null;
            }
            if (StringUtils.isEmpty(weight) && StringUtils.isEmpty(height) && StringUtils.isEmpty(headCircumference)) {
                return null;
            }
            if (StringUtils.isEmpty(weight)) {
                weight = null;
            }
            if (StringUtils.isEmpty(height)) {
                height = null;
            }
            if (StringUtils.isEmpty(headCircumference)) {
                headCircumference = null;
            }

            String authorId = (String) argMap.get("authorId");
            String tenantId = (String) argMap.get("tenantId");
            String testTime = (String) argMap.get("finishDate");
            if (StringUtils.isEmpty(testTime)) {
                testTime = DateUtil.getCurrDate2();
            }

            Map<String, Object> jsonData = new HashMap<String, Object>();
            jsonData.put("authorId", authorId);
            jsonData.put("userId", userId);
            jsonData.put("weight", weight);
            jsonData.put("height", height);
            jsonData.put("tenantId", tenantId);
            jsonData.put("testTime", testTime);
            jsonData.put("headCircumference", headCircumference);
            jsonData.put("sourceType", Constants.SOURCE_TYPE_FOLLOW_TEST);
            Map<String, Object> retOut = familyReportService.addGrowthRecord(jsonData);

            return retOut;
        }

        return null;
    }

    /**
     * 建档任务需要考虑患者修改基本信息
     */
    public Map<String, Object> dealTaskContUserInfo(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramIn);

        String updateAccept = (String) argMap.get("updateAccept");
        String userId = (String) argMap.get("userId");
        String updateTime = (String) argMap.get("updateTime");
        // String authorId = (String) argMap.get("authorId");
        String tenantId = (String) argMap.get("tenantId");
        // String authorName = (String) argMap.get("authorName");
        // String queueId = (String) argMap.get("queueId");
        String currPhoneNum = (String) argMap.get("currPhoneNum");
        String userType = (String) argMap.get("userType");

        Map<String, Object> queueMap = new HashMap<String, Object>();
        Map<String, Object> quesMap = (JSONObject) argMap.get("contentData");
        if (!MapUtils.isEmpty(quesMap)) {
            Map<String, Object> userMapIn = ToolUtils.parseUserInfoByQues(quesMap);
            //2018-01-02
            if (userMapIn != null && userMapIn.size() > 0) {
                paramIn.putAll(userMapIn);
            }
            if (!MapUtils.isEmpty(userMapIn)) {
                int pregnancyDay = 0;
                try {
                    pregnancyDay = (int) userMapIn.get("pregnancyDay");
                } catch (Exception e) {
                }
                if (pregnancyDay > 500) {
                    throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_INPUT_DATA_VERIFY_ERROR,
                            "尊敬的用户，您填写的出生日期或者预产期不正确，请检查！");
                }

                /**
                 * 增加患者信息入参 start ---- 2018-01-02
                 * 并判断时间生日和预产期是否发生变化
                 **/
                this.dealUserBirInfo(paramIn);
                /**
                 *增加患者信息入参 end ---- 2018-01-02
                 **/

                userMapIn.put("userId", userId);
                userMapIn.put("updateTime", updateTime);
                List<String> tenantIdList = new ArrayList<String>();
                tenantIdList.add(tenantId);
                tenantIdList.add(Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
                userMapIn.put("tenantIdList", tenantIdList);

                // 根据用户类型 母亲或宝宝
                userMapIn.put("userType", userType);
                // 修改当前租户id和默认0的基本信息
                patientDao.updatePatientInfoById(userMapIn);
                // 历史表记录
                Map<String, Object> userHisMap = new HashMap<String, Object>();
                userHisMap.put("userId", userId);
                userHisMap.put("updateTime", updateTime);
                userHisMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
                userHisMap.put("updateAccept", updateAccept);
                userHisMap.put("tenantIdList", tenantIdList);
                patientDao.savePatientHisInfo(userHisMap);

                // 判断手机号码是否有变化，如果有变化，需要通知app侧调整，发送新的注册消息
                String newPhoneNo = (String) userMapIn.get("phoneNo");
                if (!StringUtils.isEmpty(newPhoneNo)) {
                    if (!newPhoneNo.equals(currPhoneNum)) {
                        // 设置标志位 ：同步流程放到最后
                        queueMap.put("newPhoneNo", newPhoneNo);
                    }
                }
            }
        }

        // 科研编号修改，查询配置表中的配置的id
        Map<String, Object> staticMap = new HashMap<String, Object>();
        staticMap.put("type", Constants.CONTENT_DATA_TYPE);
        List<Map<String, Object>> quesList = confCacheDao.selectBsStaticParamByCondition(staticMap);
        if (!CollectionUtils.isEmpty(quesList)) {
            List<String> hisNoList = new ArrayList<String>();
            int kk = 0;
            int quesSize = quesList.size();
            Map<String, Object> confMap = new HashMap<String, Object>();
            for (kk = 0; kk < quesSize; kk++) {
                confMap = quesList.get(kk);
                String confId = (String) quesMap.get(confMap.get("paramCode"));
                if (null != confId) {
                    // 空值支持修改
                    hisNoList.add(confId);
                }
            }
            // 目前只考虑最大3个研究id
            int inum = hisNoList.size();
            for (kk = 0; kk < inum; kk++) {
                if (0 == kk) {
                    queueMap.put("hisNo1", hisNoList.get(kk));
                } else if (1 == kk) {
                    queueMap.put("hisNo2", hisNoList.get(kk));
                } else if (2 == kk) {
                    queueMap.put("hisNo3", hisNoList.get(kk));
                } else {
                    logger.warn("ignore his_no[" + kk + "]==" + hisNoList.get(kk));
                }
            }
        }

        return queueMap;
    }


    /**
     * 解析判断当前孕产期和生日是否发生变化
     * 2018-01-03
     */
    public Map<String, Object> dealUserBirInfo(Map<String, Object> paramIn) throws Exception {
        Patient pt = (Patient) paramIn.get("patient");
        boolean flag = false;//判断是否出现生日或者预产期修改
        String currDay = DateUtil.getCurrDate();
        String updateAccept = (String) paramIn.get("updateAccept");//流水
        String updateTime = (String) paramIn.get("updateTime");//更新时间
        String updateType = Constants.UPDATE_TYPE_UPDATE_X;//更新类型
        String updateAuthor = (String) paramIn.get("authorId");//更新医生id
        Map<String, Object> executeMapIn = new HashMap<String, Object>();
        // 出生日期
        String birthday = (String) paramIn.get("birthday");
//        System.out.println("1111"+birthday);
//        System.out.println(pt.getBirthday());
        if (!StringUtils.isBlank(birthday)) {
            birthday = birthday.trim();
            if (!StringUtils.isBlank(pt.getBirthday()) && !birthday.equals(pt.getBirthday())) {
                flag = true;
            }
        }
        // 预产期
        String expectedDay = (String) paramIn.get("expectedDay");
        if (!StringUtils.isBlank(expectedDay)) {
            expectedDay = expectedDay.trim();
            if (!StringUtils.isBlank(pt.getExpectedDay()) && !expectedDay.equals(pt.getExpectedDay())) {
                flag = true;
            }
        }
        if (flag) {
            int iPrenDay = 280;
            if (!StringUtils.isBlank(expectedDay) && !StringUtils.isBlank(birthday)) {
                iPrenDay = ToolUtils.calPrenDayByBirthAndExpect(birthday, expectedDay);
            }
            executeMapIn.put("currDay", currDay);
            executeMapIn.put("prenDay", iPrenDay);
            executeMapIn.put("birthDay", birthday);
            if (!StringUtils.isEmpty(birthday)) {// 微信产妇建档 可能没有生日选项
                executeMapIn.put("ageDay", ToolUtils.getBirthAgeDay(birthday));
            }
            // 出院日期，暂无，先写上
            executeMapIn.put("outHospitalDay", paramIn.get("outHospitalDay"));
            // 初检孕周及末次月经日期（孕产妇随访）
            executeMapIn.put("firstChkPregWeek", paramIn.get("firstChkPregWeek"));
            executeMapIn.put("lastMenstruationDate", paramIn.get("lastMenstruationDate"));
            executeMapIn.put("deliveryDate", paramIn.get("deliveryDate"));

            // 队列信息校验
            HashMap<String, Object> queueMap = new HashMap<String, Object>();
            queueMap.put("id", paramIn.get("queueId"));
            List<FollowQueue> queueList = queueDao.selectById(queueMap);
            if (null == queueList || 0 == queueList.size()) {
                logger.info("没有查询到方案信息！");
                return null;
            }
            FollowQueue fq = (FollowQueue) queueList.get(0);
            /**
             * 查询当前患者的任务信息
             * 1.已完成任务排除
             * 2.以过期的任务需要查询，看修改生日或者其他时间的时候当前任务是否
             * 还处于过期状态若没有需要将过期改成正常为随访状态，开始结束时间和触发时间
             * 3.修改未随访任务开始结束时间和触发时间
             **/
            Map<String, Object> nextMap = new HashMap<String, Object>();
            nextMap.put("ptSchemeId", paramIn.get("ptSchemeId"));
            nextMap.put("revSeqNo", Constants.TASK_SEQ_FOR_INIT);
            nextMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
            // 不查临时任务
            nextMap.put("temporaryTask", "1");
            nextMap.put("seqNoOrderAsc", "1");
            //查询pt_task_info除建档以外的门诊任务
            List<PatientTask> nextTaskList = patientTaskDao.select(nextMap);
            int suffWinDay = 0;// 后窗口期
            int iWinDay = 0;// 前窗口期
            String taskStatus = "";
            String schemeVersionid = registerQuery(fq.getSchemeId());
            for (int i = 0; i < nextTaskList.size(); i++) {
                Map<String, Object> mapIn = new HashMap<String, Object>();
                // 查询当前队列对应方案门诊任务
                PatientTask ptTaks = nextTaskList.get(i);
                HashMap<String, Object> taskQueryParam = new HashMap<String, Object>();
                taskQueryParam.put("schemeVersionid", schemeVersionid);
                taskQueryParam.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 0：门诊随访
                // 不查建档方案问卷
                taskQueryParam.put("revSeqNo", Constants.TASK_SEQ_FOR_INIT);
//	            taskQueryParam.put("seqNo", ptTaks.getSeqNo());
                //查询当前方案任务fu_task_info
                List<FollowTask> taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
                if (null == taskList || 0 == taskList.size()) {
                    continue;
                }
                FollowTask ft = taskList.get(i);
                int iTaskSeq = ft.getSeqNo();
                int iCycleDay = ft.getCycleDay();
                // 触发方式
                String executeType = ft.getExecuteType();
                if (!Constants.SCHEME_TASK_EXECUTE_TYPE_1.equals(executeType) && !Constants.SCHEME_TASK_EXECUTE_TYPE_2.equals(executeType)) {
                    continue;
                }
                executeMapIn.put("executeType", executeType);
                executeMapIn.put("taskSeq", iTaskSeq);
                executeMapIn.put("cycleDay", iCycleDay);
                executeMapIn.put("executeDay", ft.getExecuteDay());
                String endTime = "";
                String executeTime = "";
                //处理任务时间
                if (!StringUtils.isEmpty(birthday)) {// 微信产妇建档 可能没有生日选项
                    //获取执行时间
                    executeTime = ToolUtils.getExecuteTime(executeMapIn);
                    iWinDay = ft.getWindowDay();
                    suffWinDay = ft.getSuffixWindowDay();
                    endTime = DateUtil.calcDay(executeTime, "+", suffWinDay);
                } else {
                    executeTime = currDay;
                    endTime = currDay;
                }
                //任务开始时间
                String beginTime = DateUtil.calcDay(executeTime, "-", iWinDay);
                mapIn.put("executeTime", executeTime);
                mapIn.put("beginTime", beginTime);
                mapIn.put("endTime", endTime);
                mapIn.put("taskId", ptTaks.getId());
                mapIn.put("updateAccept", updateAccept);
                mapIn.put("updateTime", updateTime);
                mapIn.put("updateType", updateType);
                mapIn.put("updateAuthor", updateAuthor);
                mapIn.put("ptSchemeId", paramIn.get("ptSchemeId"));
                mapIn.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);

                if (Constants.PATIENT_TASK_STATUS_EXPIRED.equals(ptTaks.getTaskStatus()) && StringUtils.isBlank(ptTaks.getFinishDate())) {
                    if (endTime.compareTo(currDay) > 0) {
                        taskStatus = "0";
                        mapIn.put("taskStatus", taskStatus);
                        //删除失访记录表中的数据
                        patientTaskDao.removeLostInfoByTaskId(mapIn);
                    }
                } else {
                    // 入失访记录表
                    if (endTime.compareTo(currDay) < 0 && Constants.PATIENT_TASK_STATUS_INIT.equals(ptTaks.getTaskStatus())) {
                        PtLostRd prdVo = new PtLostRd();
                        prdVo.setAuthorId(updateAuthor);
                        prdVo.setCreateTime(updateTime);
                        prdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_LOST_ID));
                        prdVo.setLostDate(endTime);
                        prdVo.setPtSchemeid(ptTaks.getPtSchemeid());
                        prdVo.setQueueId(ptTaks.getQueueId());
                        prdVo.setReasonId("");
                        prdVo.setTaskId(ptTaks.getId());
                        prdVo.setTaskName(ft.getTaskName());
                        prdVo.setUpdateAccept(updateAccept);
                        prdVo.setUpdateTime(updateTime);
                        prdVo.setUserId(ptTaks.getUserId());
                        patientTaskDao.savePatientLostInfo(prdVo);
                        taskStatus = "2";
                        mapIn.put("taskStatus", taskStatus);
                    }
                }
                patientTaskDao.updatePtTaskptTaskId(mapIn);
                patientTaskDao.insertPtTaskHisByPtSchemeId(mapIn);
            }
        }
        //查询当前队列任务方案对应的门诊任务信息
        return paramIn;

    }

    // 患者任务内容修改接口实现
    @Transactional
    public void modTaskContentData(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);

        String opType = (String) argMap.get("opType");
        String cntDataTempType = (String) argMap.get("type");
        String opCode = (String) argMap.get("opCode");
        String sourceType = (String) argMap.get("sourceType");// 来源渠道
        if (StringUtils.isBlank(sourceType)) {
            // 默认web端门诊渠道
            sourceType = Constants.PATIENT_SOURCE_TYPE_DOOR;
        }

        String taskId = (String) argMap.get("taskId");
        String updateAccept = (String) argMap.get("updateAccept");
        String ptSchemeId = (String) argMap.get("ptSchemeId");
        String userId = (String) argMap.get("userId");
        String updateTime = (String) argMap.get("updateTime");
        String authorId = (String) argMap.get("authorId");
        String tenantId = (String) argMap.get("tenantId");
        String authorName = (String) argMap.get("authorName");
        String queueId = (String) argMap.get("queueId");
        String zhusuType = (String) argMap.get("zhusuType");
        String phoneNo = (String) argMap.get("phoneNo");
        String cardNo = (String) argMap.get("cardNo");
        String zjhm = (String) argMap.get("zjhm");
        String pathash = (String) argMap.get("pathash");
        String bookid = (String) argMap.get("bookid");
        Integer opRecordDealFlag = (Integer) argMap.get("opRecordDealFlag");// 离线时先建档，再提交任务，此时不需要再插操作记录
        if (null == opRecordDealFlag) {
            opRecordDealFlag = 0;
        }
        // 辅助生殖修改用户信息可能需要同时修改用户扩展信息
        Map<String, Object> mapIn = (JSONObject) argMap.get("extendInfo");
        if (null != mapIn) {
            List<PtUserextendInfo> ptAcBatchList = new ArrayList<PtUserextendInfo>();
            Iterator<String> iter = mapIn.keySet().iterator();
            String key = "";
            int pr = 0;
            while (iter.hasNext()) {
                key = iter.next();
                PtUserextendInfo ptExtVo = new PtUserextendInfo();
                ptExtVo.setUserId(userId);
                ptExtVo.setAuthorId(authorId);
                ptExtVo.setCreateTime(updateTime);
                ptExtVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_SYSTEMID));
                ptExtVo.setParamName(key);
                ptExtVo.setParamValue("" + mapIn.get(key));
                if ("alternateNo".equals(key)) {
                    ptExtVo.setRemark(phoneNo);
                } else {
                    ptExtVo.setRemark("");
                }
                ptExtVo.setUpdateTime(updateTime);
                ptExtVo.setQueueId(queueId);
                ptExtVo.setTenantId(tenantId);
                // 逐条更新用户扩展信息
                pr = ptExtendDao.updateDataByUserId(ptExtVo);
                if (pr == 0) {
                    ptAcBatchList.add(ptExtVo);
                }
            }
            if (ptAcBatchList != null && ptAcBatchList.size() > 0) {
                // 入患者扩展信息pt_userextend_info
                ptExtendDao.savePatientExtendBatch(ptAcBatchList);
            }
        }
        String deptId = (String) argMap.get("deptId");
        // 生物样本收集记录（安医大需求）
        List<Map<String, Object>> sampleList = ToolUtils.typeCast(argMap.get("sampleList"));
        if (!CollectionUtils.isEmpty(sampleList)) {
            Map<String, Object> sampleMap = new HashMap<String, Object>();
            sampleMap.put("userId", userId);
            sampleMap.put("ptSchemeId", ptSchemeId);
            sampleMap.put("updateTime", updateTime);
            sampleMap.put("authorId", authorId);
            sampleMap.put("tenantId", tenantId);
            sampleMap.put("queueId", queueId);
            sampleMap.put("sampleList", sampleList);
            this.dealSampleInfo(sampleMap);
        }

        // JSONArray ptContentIds = (JSONArray) argMap.get("ptContentIds");
        boolean appInvokeFlag = false;// app调用标志
        if (!StringUtils.isEmpty((String) argMap.get("invokeType"))) {
            // app侧调用无租户id等信息
            appInvokeFlag = true;
        }

        HashMap<String, Object> commMap = new HashMap<String, Object>();
        commMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        commMap.put("updateTime", updateTime);
        commMap.put("updateAccept", updateAccept);

        // 校验任务信息
        Map<String, Object> taskMapIn = new HashMap<String, Object>();
        taskMapIn.put("taskId", taskId);
        List<PatientTask> ptVoList = patientTaskDao.selectById(taskMapIn);
        if (CollectionUtils.isEmpty(ptVoList)) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASK_NOT_EXIST, "该患者当前任务不存在！");
        }
        PatientTask currTaskVo = ptVoList.get(0);
        int taskSeqNo = currTaskVo.getSeqNo();
        String taskType = currTaskVo.getTaskType();
        String ruleType = currTaskVo.getRuleType();
        if (StringUtils.isEmpty(ruleType)) {
            ruleType = "";
        }
        // 任务审核状态
        String taskAuditStatus = currTaskVo.getAuditStatus();
        if (StringUtils.isBlank(taskAuditStatus)) {
            taskAuditStatus = Constants.PATIENT_TASK_AUDIT_STATUS_INIT;
        } else if (Constants.PATIENT_TASK_AUDIT_STATUS_NORMAL.equals(taskAuditStatus)) {
            // 已审核通过
            if (Constants.PATIENT_SOURCE_TYPE_SCAN.equals(sourceType)) {
                // 诊间扫码渠道
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_PT_SACN_SYNC_DATA_FOR_AUDITED,
                        "患者填写信息医生已确认，无法同步修改！"));
            }
        }

        // 队列信息校验
        HashMap<String, Object> queueInMap = new HashMap<String, Object>();
        queueInMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueInMap);
        if (null == queueList || 0 == queueList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }

        // 患者信息
        Map<String, Object> userInMap = new HashMap<String, Object>();
        userInMap.put("userId", userId);
        if (StringUtils.isEmpty(tenantId)) {
            tenantId = queueList.get(0).getTenantId();
            // app调用
            if (StringUtils.isEmpty(tenantId) && appInvokeFlag) {
                tenantId = Constants.PT_USER_INFO_DEFAULT_TENANT_ID;
            }
        }
        userInMap.put("tenantId", tenantId);
        Patient ptOut = patientDao.selectById(userInMap);
        if (null == ptOut) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
        }
        argMap.put("tenantId", tenantId);

        // 解析任务内容（问卷）
        String contTemplType = "";
        if (!StringUtils.isEmpty(cntDataTempType)) {
            contTemplType = cntDataTempType;
        }
        JSONObject jsonData = new JSONObject(argMap);
        Map<String, Object> quesMap = (JSONObject) jsonData.getJSONObject("contentData");


        if (null == quesMap || 0 == quesMap.size()) {
            logger.warn("无问题--答案记录");
            // return;
        } else if (StringUtils.isEmpty(contTemplType)) {
            contTemplType = (String) quesMap.get(Constants.QUESTION_ID_FOR_CONTTEMPLTYPE);
        }
        // 建档任务需要考虑患者修改基本信息
        Map<String, Object> queueMap = new HashMap<String, Object>();
        String newPhoneNo = null; // 修改手机号码标志 true 需要同步app
        argMap.put("patient", ptOut);//2018-01-02
        if (Constants.TASK_SEQ_FOR_INIT == taskSeqNo) {
            argMap.put("currPhoneNum", ptOut.getPhoneNo());
            queueMap = this.dealTaskContUserInfo(argMap);

            if (null != queueMap.get("newPhoneNo")) {
                newPhoneNo = (String) queueMap.get("newPhoneNo");
                queueMap.remove("newPhoneNo");
            }
            if (Constants.PATIENT_SOURCE_TYPE_DOOR.equals(sourceType)) {
                // 门诊渠道，则确认建档
                queueMap.put("confirmFlag", Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CONFIRM_SUCCESS);
            }
        }
        queueMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        queueMap.put("updateTime", updateTime);
        queueMap.put("updateAccept", updateAccept);
        // 生长发育题型，调用接口入表FamilyReportService.addGrowthRecord
        this.dealGrowthDevApi(argMap);

        // 入操作流水记录表 ia_operation_record
        if (0 == opRecordDealFlag) {
            Map<String, Object> paramRecord = new HashMap<String, Object>();
            paramRecord.put("userName", ptOut.getUserName());
            paramRecord.put("userId", userId);
            paramRecord.put("queueId", queueId);
            paramRecord.put("authorId", authorId);
            paramRecord.put("opTime", updateTime);
            if (Constants.OP_TYPE_SELF.equals(opType)) {
                paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_8);
            } else {
                paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_9);
            }
            if (Constants.OP_TYPE_SELF.equals(opType)) {
                paramRecord.put("opUsertype", Constants.OPCODE_TYPE_PATIENT);
            } else {
                paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
            }
            paramRecord.put("authorName", authorName);
            paramRecord.put("opCode", opCode);
            paramRecord.put("updateAccept", updateAccept);
            paramRecord.put("tenantId", tenantId);
            paramRecord.put("remark", argMap.get("opNote"));
            paramRecord.put("opType", opType);
            paramRecord.put("taskId", taskId);
            Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
            patientOperationRecordDao.saveOperationRecord(outRecord);
        }

        // 判断是否为该任务第一次录入数据
        int upcdFlag = 0;
        String opTime = "";
        HashMap<String, Object> qryConMap = new HashMap<String, Object>();
        qryConMap.put("taskId", taskId);
        qryConMap.put("contDataTemplType", contTemplType);
        if (Constants.TASK_TYPE_NONSCHEME_REALTIME.equals(taskType)) {
            // 主诉登记
            if (Constants.TASK_TYPE_SCHEME_SELFREPORT_COMMON.equals(ruleType)) {
                // 通用主诉规则
                opTime = DateUtil.getCurrDate();
                qryConMap.put("opTime", opTime);// 今天是否已经录入过了
            } else if (Constants.TASK_TYPE_SCHEME_SELFREPORT_MONTHAGE.equals(ruleType)) {
                // 纠正月龄主诉规则（待完善）
            }
        }
        List<PatientContentData> ptTaskConList = patientTaskConDao.selectContentDataByTaskId(qryConMap);
        if (null != ptTaskConList && 0 != ptTaskConList.size()) {
            // 非第一次录入，更新
            upcdFlag = 0;
        } else {
            // 第一次录入，插入
            upcdFlag = 1;
        }

        // 拼装问题和答案，准备入表pt_contentdata_info
        if (MapUtils.isNotEmpty(quesMap)) {
            if (1 == upcdFlag) {
                List<PatientContentData> ptcInList = new ArrayList<PatientContentData>();
                Iterator<String> iter = quesMap.keySet().iterator();
                while (iter.hasNext()) {
                    PatientContentData pcdVo = new PatientContentData();
                    String queskey = iter.next();
                    String quesvalue = (String) quesMap.get(queskey);

                    pcdVo.setContentId("");
                    pcdVo.setCreateTime(updateTime);
                    pcdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTDATAID));
                    pcdVo.setQuestionAnswer(quesvalue);
                    pcdVo.setQuestionId(queskey);
                    pcdVo.setTaskId(taskId);
                    pcdVo.setUpdateAccept(updateAccept);
                    pcdVo.setUpdateTime(updateTime);
                    pcdVo.setUpdateType(Constants.UPDATE_TYPE_INSERT);
                    pcdVo.setUserId(userId);
                    pcdVo.setPtSchemeid(ptSchemeId);
                    pcdVo.setTemplType(contTemplType);
                    pcdVo.setOpTime(opTime);
                    pcdVo.setQueueId(queueId);
                    pcdVo.setTenantId(tenantId);
                    pcdVo.setSourceTypeCreate(sourceType);
                    pcdVo.setSourceTypeUpdate(sourceType);
                    ptcInList.add(pcdVo);
                }
                // 批量插入
                patientTaskConDao.savePatientTaskContentDataBatch(ptcInList);
                patientTaskConDao.savePatientTaskContentDataHisBatch(ptcInList);
            } else {


                //2020.7.1 更新 全部更新改为判断是否更改然后更新

                HashMap taskIdMap = new HashMap();
                taskIdMap.put("taskId", taskId);
                List<PatientContentData> oldPatientTask = patientTaskConDao.selectContentDataByTaskId(taskIdMap);
                List<PatientContentData> updatePatientTask = new ArrayList<PatientContentData>();
                List<PatientContentData> ptcInList = new ArrayList<PatientContentData>();
                Set<String> existSet = new HashSet();
                for (PatientContentData x : oldPatientTask) {
                    existSet.add(x.getQuestionId());
                }
                ;
                Iterator<String> iter = quesMap.keySet().iterator();
                while (iter.hasNext()) {
                    String x = iter.next();
                    if (!existSet.contains(x)) {
                        PatientContentData pa = new PatientContentData();
                        pa.setQuestionId(x);
                        oldPatientTask.add(pa);
                    }
                }
                for (PatientContentData x : oldPatientTask) {
                    //对比questionId
                    if (x.getId() != null) {
                        //判断答案是否修改
                        if (quesMap.get(x.getQuestionId()) != null && !quesMap.get(x.getQuestionId()).equals(x.getQuestionAnswer())) {
                            x.setQuestionAnswer(quesMap.get(x.getQuestionId()).toString());
                            x.setUpdateTime(updateTime);
                            x.setUpdateAccept(updateAccept);
                            x.setOpTime(opTime);
                            x.setSourceTypeUpdate(sourceType);
                            x.setTemplType(contTemplType);
                            updatePatientTask.add(x);
                        }
                    } else {//不存在
                        // 新增题型，需要插入
                        PatientContentData pcdVo = new PatientContentData();
                        pcdVo.setContentId("");
                        pcdVo.setCreateTime(updateTime);
                        pcdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTDATAID));
                        if (quesMap.get(x.getQuestionId()) == null) {
                            pcdVo.setQuestionAnswer(null);
                        } else {
                            pcdVo.setQuestionAnswer(quesMap.get(x.getQuestionId()).toString());
                        }
                        pcdVo.setQuestionId(x.getQuestionId());
                        pcdVo.setTaskId(taskId);
                        pcdVo.setUpdateAccept(updateAccept);
                        pcdVo.setUpdateTime(updateTime);
                        pcdVo.setUpdateType(Constants.UPDATE_TYPE_INSERT);
                        pcdVo.setUserId(userId);
                        pcdVo.setPtSchemeid(ptSchemeId);
                        pcdVo.setTemplType(contTemplType);
                        pcdVo.setOpTime(opTime);
                        pcdVo.setQueueId(queueId);
                        pcdVo.setTenantId(tenantId);
                        pcdVo.setSourceTypeCreate(sourceType);
                        pcdVo.setSourceTypeUpdate(sourceType);
                        ptcInList.add(pcdVo);
                    }
                    //Edit by jiangq on 2023年10月16日 处理多级题型的删除问题
                    //新保存的值
                    List<String> newQuestionIds = new ArrayList<>();
                    quesMap.entrySet().stream().forEach(entry -> {
                        if (entry.getKey().contains("rowNumber")) {
                            newQuestionIds.add(entry.getKey());
                        }
                    });
                    //原本的值
                    List<String> existIds = existSet.stream().filter(e -> e.contains("rowNumber")).collect(Collectors.toList());
                    List<String> delIds = (List<String>) org.apache.commons.collections.CollectionUtils.removeAll(existIds, newQuestionIds);
                    System.out.println(delIds);
                    PatientContentData patientContentData;
                    for (String delId : delIds) {
                        patientContentData = new PatientContentData();
                        patientContentData.setTaskId(taskId);
                        patientContentData.setQuestionId(delId);
                        patientContentData.setUserId(userId);
                        //TODO by jiangq on 2023年10月16日 后续可更改批量删除
                        patientTaskConDao.deletePtContentDataInfoByConDt(patientContentData);
                    }
                }

                if (!CollectionUtils.isEmpty(ptcInList)) {
                    patientTaskConDao.savePatientTaskContentDataBatch(ptcInList);
                }
                if (!CollectionUtils.isEmpty(updatePatientTask)) {
                    patientTaskConDao.updateBatchPatientContentData(updatePatientTask);
                }
                // 更新历史轨迹
                HashMap<String, Object> hisConDataMap = new HashMap<String, Object>();
                hisConDataMap.put("taskId", taskId);
                hisConDataMap.put("updateAccept", updateAccept);
                hisConDataMap.put("updateTime", updateTime);
                hisConDataMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
                hisConDataMap.put("contTemplType", contTemplType);
                hisConDataMap.put("opTime", opTime);
                patientTaskConDao.insertContentDataHis(hisConDataMap);
            }
        }

        if ("Y".equals(zhusuType)) {
            Map<String, Object> mapInfo = new HashMap<String, Object>();
            mapInfo.put("id", "66");
            Map<String, Object> mapOut = new HashMap<String, Object>();
            mapOut = patientDao.selectoutTableInfo(mapInfo);
            if (!CollectionUtils.isEmpty(mapOut)) {
                Date date = new Date();
                String datenow = DateUtil.getDate_8(date);
                String json = mapOut.get("template").toString();
                JSONObject jsonTow = (JSONObject) argMap.get("contentData");
                mapOut = ToolUtils.appadd(json, jsonTow);// 拼接入参
                mapOut.put("phoneNo", phoneNo);
                mapOut.put("cardNo", cardNo);
                mapOut.put("zjhm", zjhm);
                String dbcs = (String) mapOut.get("dbcs");
                String dbcs2 = (String) mapOut.get("dbcs2");
                String dnsj = (String) mapOut.get("dnsj");
                mapOut.put("code", Constants.STRING_SERVICECODE_A09U002O);
                mapOut.put("dbcs2", Integer.parseInt(dbcs2));
                mapOut.put("dbcs", Integer.parseInt(dbcs));
                if (((String) mapOut.get("wyfs")).indexOf("人工") == -1) {
                } else {
                    mapOut.put("wyfs", "人工");
                }
                if (StringUtils.isBlank((String) mapOut.get("dnsj"))) {
                    mapOut.put("dnsj", datenow);
                    dnsj = "";
                } else {
                    dnsj = (String) mapOut.get("dnsj");
                }
                // System.out.print("mapOut###########" + mapOut);
                // 调用远端接口
                mapOut.put("patName", authorName);
                mapOut.put("pathash", pathash);
                mapOut.put("platform_code", Constants.SOURCE_TPLATFORM_CODE);
                mapOut.put("platform_key", userId);
                mapOut.put("bookid", bookid);
                mapOut.put("ptSchemeId", ptSchemeId);
                mapOut.put("userId", userId);
                /*
                 * List<Map<String, Object>> list =
                 * patientDao.selectcardinfo(mapOut); // 保存在数据库中 if (list !=
                 * null && list.size() > 0) { patientDao.modDataByOutNo(mapOut);
                 * } else {
                 */
                mapOut.put("create_time", updateTime);
                mapOut.put("outpatno", pathash);
                mapOut.put("cardName", "就诊卡");
                logger.info("zhusu : " + mapOut.toString());
                patientDao.savetrbkfjbxxInfo(mapOut);

                // }
                mapOut.remove("cardNo");
                mapOut.remove("userId");
                mapOut.remove("farzy");
                mapOut.remove("farhfyrxm");
                mapOut.remove("phoneNo");
                mapOut.remove("farhcd");
                mapOut.remove("ptSchemeId");
                mapOut.remove("zjhm");
                mapOut.remove("outpatno");
                mapOut.remove("cardName");
                mapOut.remove("create_time");
                mapOut.put("dnsj", dnsj);
                logger.info(mapOut.toString());
                String asg = bizInterClient.call(Constants.SERVICE_NAME_FOR_SERVICE, "", mapOut);
                logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~:" + asg);
                List<Map<String, Object>> lists = ToolUtils.FormatXml(asg);
                logger.info("#########@@@@@@@@@@@@@@@@@@@@" + lists.toString());
            } else {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "没有配置表字段对应值，请联系系统管理员！"));
            }
        }

        // pt_taskcontent_rd 患者任务内容记录（按内容类型templ_type记录，相同templ_type只记录一次）
        String rdType = "";
        if (1 == upcdFlag) {
            rdType = Constants.UPDATE_TYPE_INSERT;
        } else {
            rdType = Constants.UPDATE_TYPE_UPDATE_X;
        }
        PtTaskContentRd ptcrd = new PtTaskContentRd();
        ptcrd.setCreateTime(updateTime);
        ptcrd.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_SYSTEMID));
        ptcrd.setPtSchemeid(ptSchemeId);
        ptcrd.setRemark("");
        ptcrd.setTaskId(taskId);
        ptcrd.setTemplType(contTemplType);
        ptcrd.setUpdateAccept(updateAccept);
        ptcrd.setUpdateTime(updateTime);
        ptcrd.setUpdateType(rdType);
        ptcrd.setUserId(userId);
        patientTaskConDao.insertTaskContentRd(ptcrd);

        // pt_task_info更新及历史轨迹变化记录
        HashMap<String, Object> taskMap = new HashMap<String, Object>(commMap);
        if (Constants.PATIENT_SOURCE_TYPE_DOOR.equals(sourceType)) {
            // 门诊渠道，则确认
            taskMap.put("auditStatus", Constants.PATIENT_TASK_AUDIT_STATUS_NORMAL);
        } else if (Constants.PATIENT_SOURCE_TYPE_SCAN.equals(sourceType)
                && Constants.PATIENT_TASK_AUDIT_STATUS_INIT.equals(taskAuditStatus)) {
            // 诊间扫码渠道，且任务审核状态为初始化，则更新为待审核
            taskMap.put("auditStatus", Constants.PATIENT_TASK_AUDIT_STATUS_CHECKING);
        } else {
            // 待扩展
        }
        taskMap.put("taskId", taskId);
        // 查询该任务下是否有医生门诊任务内容
        boolean chkTemplFlag = false;
        if (Constants.OP_TYPE_DOOR.equals(opType)) {
            // 当前问卷就是门诊问卷
            chkTemplFlag = true;
        } else {
            // 当前问卷不是门诊问卷
            Map<String, Object> taskConMap = new HashMap<String, Object>(commMap);
            taskConMap.put("taskId", taskId);
            taskConMap.put("contTemplType", Constants.QUESTIONNAIRE_TYPE_0);
            List<PatientTaskContent> ptConDataList = patientTaskConDao.selectContentByTaskId(taskConMap);
            // 任务下有门诊问卷
            if (!CollectionUtils.isEmpty(ptConDataList)) {
                chkTemplFlag = false;
            } else {
                chkTemplFlag = true;
            }
        }
        if (Constants.TASK_TYPE_SCHEME_TEMP.equals(taskType)) {
            // 线上问卷更新
            chkTemplFlag = true;
            queueMap.put("onlineFinishIncr", 1);
        } else if (Constants.TASK_TYPE_NONSCHEME_REALTIME.equals(taskType)) {
            // 主诉登记更新
            queueMap.put("selfReportFinishIncr", 1);
            if (Constants.TASK_TYPE_SCHEME_SELFREPORT_COMMON.equals(ruleType)) {
                // 通用主诉规则
                chkTemplFlag = false;
            } else if (Constants.TASK_TYPE_SCHEME_SELFREPORT_MONTHAGE.equals(ruleType)) {
                // 纠正月龄主诉规则（待完善）
            }
        }

        String taskStatus = currTaskVo.getTaskStatus();
        // 若有医生任务，等医生完成后，该任务才能关闭
        boolean ptSchemeFlag = false;
        if (Constants.PATIENT_TASK_STATUS_INIT.equals(taskStatus) && chkTemplFlag) {
            taskMap.put("taskStatus", Constants.PATIENT_TASK_STATUS_FINISH);
            ptSchemeFlag = true;
        }
        taskMap.put("updateAuthor", authorId);
        if (Constants.OP_TYPE_DOOR.equals(opType)) {
            taskMap.put("updateAuname", (String) argMap.get("updateAuname"));
        }
        // 门诊录入完成时间（为打印使用），根据随访日期处理（当天录入则更新finish_time）
        String finishDateNew = (String) argMap.get("finishDate");
        if (StringUtils.isNotBlank(finishDateNew)) {
            taskMap.put("finishDate", finishDateNew);
            taskMap.put("finishTime", updateTime);
        }
        taskMap.put("taskNote", (String) argMap.get("taskNote"));
        String nextDate = (String) argMap.get("nextDate");
        String nextAddress = (String) argMap.get("nextAddress");
        if (!StringUtils.isEmpty(nextDate)) {
            taskMap.put("nextDate", nextDate);
        }
        if (!StringUtils.isEmpty(nextAddress)) {
            taskMap.put("nextAddress", nextAddress);
        }
        int upret = patientTaskDao.updatePatientTaskById(taskMap);
        if (0 == upret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_TASK_NOT_EXIST, "患者当前任务不存在！"));
        }
        patientTaskDao.insertPatientTaskHisById(taskMap);

        // 更新下次随访任务的execute_time或execute_address
        if (!StringUtils.isEmpty(nextDate) || !StringUtils.isEmpty(nextAddress)) {
            // 查询下次task信息
            String nextTaskId = currTaskVo.getNextTaskId();
            if (StringUtils.isEmpty(nextTaskId)) {
                // 兼容老数据
                Map<String, Object> nextMap = new HashMap<String, Object>();
                nextMap.put("ptSchemeId", currTaskVo.getPtSchemeid());
                nextMap.put("seqNo", currTaskVo.getSeqNo() + 1);
                nextMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
                List<PatientTask> nextTaskList = patientTaskDao.select(nextMap);
                if (!CollectionUtils.isEmpty(nextTaskList)) {
                    nextTaskId = nextTaskList.get(0).getId();
                }
            }
            if (!StringUtils.isEmpty(nextTaskId)) {
                Map<String, Object> nextTaskMapIn = new HashMap<String, Object>(commMap);
                nextTaskMapIn.put("updateAuthor", authorId);
                nextTaskMapIn.put("taskId", nextTaskId);
                nextTaskMapIn.put("executeAddress", nextAddress);
                if (!StringUtils.isEmpty(nextDate)) {
                    if (-1 != nextDate.indexOf(Constants.COLON_SPLIT_STR)) {
                        String[] nextDateArr = nextDate.split(Constants.COLON_SPLIT_STR);
                        nextTaskMapIn.put("executeTime", nextDateArr[0]);
                    } else {
                        nextTaskMapIn.put("executeTime", nextDate);
                    }
                }
                // 1、下次随访任务已完成或过期，则不更新；2、更新executeTime的同时，更新begin_time和end_time
                Map<String, Object> nextMapIn = new HashMap<String, Object>();
                nextMapIn.put("taskId", nextTaskId);
                List<PatientTask> nextMapList = patientTaskDao.selectById(nextMapIn);
                if (!CollectionUtils.isEmpty(nextMapList)) {
                    PatientTask nextTaskVo = nextMapList.get(0);
                    String nextTaskStatus = nextTaskVo.getTaskStatus();
                    int nextWinDay = nextTaskVo.getWindowDay();
                    String nextExecuteTime = (String) nextTaskMapIn.get("executeTime");
                    if (StringUtils.isNotBlank(nextExecuteTime)) {
                        String nextBeginTime = DateUtil.calcDay2(nextExecuteTime, "-", nextWinDay);
                        String nextEndTime = DateUtil.calcDay2(nextExecuteTime, "+", nextWinDay);
                        nextTaskMapIn.put("beginTime", nextBeginTime);
                        nextTaskMapIn.put("endTime", nextEndTime);
                        if (Constants.PATIENT_TASK_STATUS_INIT.equals(nextTaskStatus)) {
                            patientTaskDao.updatePatientTaskById(nextTaskMapIn);
                            patientTaskDao.insertPatientTaskHisById(nextTaskMapIn);
                        }
                    }
                }
            }
            //在此处理添加新任务
            else {
                if (StringUtils.isNotEmpty(nextDate)) {
                    extendService.addNewPatientTask(paramMap);
                }

            }


        }

        // pt_queuescheme_info更新及历史轨迹变化记录
        queueMap.put("id", ptSchemeId);
        if (Constants.PATIENT_TASK_STATUS_INIT.equals(taskStatus) && ptSchemeFlag
                && Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
            queueMap.put("finishNumFlag", "1");
        }
        queueMap.put("updateAuthor", authorId);
        upret = patientQueueSchemeDao.updatePtQueueSchemeRecord(queueMap);
        if (0 == upret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_NOT_EXIST, "患者队列实例无记录！"));
        }
        patientQueueSchemeDao.insertPatientQueueSchemeHis(queueMap);

        // redis 门诊新增
        if (Constants.OP_TYPE_DOOR.equals(opType)) {
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.select(Constants.REDIS_DB_INDEX_PATIENT);

                ptQueueRedis.ptDoorAddforAuthor(authorId, jedis);
            } catch (JedisConnectionException jex) {
                logger.error("redis连接异常..." + jex.getMessage());
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
            } finally {
                if (null != jedis) {
                    try {
                        jedis.close();
                        logger.warn("close redis connection...");
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_CLOSE_FAILED,
                                "Redis缓存关闭失败!"));
                    }
                }
            }
        }

        // 如手机号变更 同步APP start： 建档修改同步（但指定队列）
        Boolean isSynchQueue = false;
        Map<String, Object> synchQueueIdMap = new HashMap<String, Object>();
        String synchQueueIds = PropertiesUtils.getProperty("modifyUserSynchAppQueueIds");
        if (StringUtils.isNotBlank(synchQueueIds)) {
            // 提取指定记录
            String synchQueueIdArr[] = synchQueueIds.split(Constants.COMMA_SPLIT_STR);
            for (int i = 0; i < synchQueueIdArr.length; i++) {
                synchQueueIdMap.put(synchQueueIdArr[i], "1");
            }
            if (null != MapUtils.getString(synchQueueIdMap, queueId) && Constants.TASK_SEQ_FOR_INIT == taskSeqNo) {
                isSynchQueue = true;
                ptOut = patientDao.selectById(userInMap);
            }
        }
        if (isSynchQueue || StringUtils.isNotEmpty(newPhoneNo)) {
            // 发消息到 患者注册 消息队列topic 放在最后处理
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("tenantId", tenantId);
            map.put("code", Constants.SMS_TEMPLATE_REGISTER_TYPE);
            String smsContent = "";
            if (StringUtils.isNotEmpty(newPhoneNo)) {
                if (!Constants.QUEUE_PATIENT_REGISTER_NOT_SEND_SMS.equals(queueList.get(0).getSmsFlag())) {
                    smsContent = bsSmsTemplateService.getSmsTemplateByCondition(map);
                }
            }
            // 根据科室管理系统 科室id 查询 关联APP端 科室id 并同步给app
            DepartmentBasic dept = null;
            Map<String, String> param = new HashMap<String, String>();
            param.put("departmentId", deptId);// 随访科室ID
            param.put("queueId", queueId);

            String appDeptId = "";
            if (!StringUtils.isBlank(deptId)) {
                map.clear();
                map.put("deptId", deptId);
                dept = deparmentBasicDao.selectAppDeptId(map);
                if (null != dept) {
                    appDeptId = String.valueOf(dept.getRefDepartmentId());
                    param.put("refDepartmentId", appDeptId);// app科室ID
                }
            }
            if (StringUtils.isNotBlank(newPhoneNo)) {
                ptOut.setPhoneNo(newPhoneNo);
            }

        }

        //如果是web后端 且有随访指导内容 则根据规则推送到消息总线
        if (Constants.PATIENT_SOURCE_TYPE_DOOR.equals(sourceType)) {
            argMap.put("schemeBusiType", Constants.SCHEME_BUSI_TYPE_0);
            scanDataSynchService.sendFollowGuidance(argMap);
        }
        return;
    }

    @Override
    public Patient getPatient(Map<String, Object> paramMap) throws Exception {
        return patientDao.selectById(paramMap);
    }

    // 患者专科袋任务类别查询接口实现
    public HashMap<String, Object> qryPatientContentCategory(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        HashMap<String, Object> retOut = new HashMap<String, Object>();

        List<HashMap<String, Object>> retList = new ArrayList<HashMap<String, Object>>();
        List<Map<String, Object>> conTemplList = patientTaskDao.selectDisCntTemplByPtSchemeId(argMap);
        if (!CollectionUtils.isEmpty(conTemplList)) {
            HashMap<String, Object> templMap = new HashMap<String, Object>();
            String conTemplStr = "";
            int it = 0;
            int size = conTemplList.size();

            Map<String, Object> equalMap = new HashMap<String, Object>();
            Map<String, Object> conMap = new HashMap<String, Object>();
            // 找出模板内容相同的问卷
            for (it = 0; it < size; it++) {
                conMap = conTemplList.get(it);
                String templType = (String) conMap.get("templType");
                String templVersionId = (String) conMap.get("templVersionid");
                if (Constants.QUESTIONNAIRE_TYPE_0.equals(templType)) {
                    templMap.put("id", templVersionId);
                    List<ContentTemplVersion> ctvList = contentTemplDao.selectContentTemplNoTextById(templMap);
                    if (null == ctvList || 0 == ctvList.size()) {
                        continue;
                    }
                    String equalId = ctvList.get(0).getEqualId();
                    if (!StringUtils.isEmpty(equalId)) {
                        equalMap.put(equalId, templVersionId);
                    }
                }
            }
            logger.warn("equalMap==" + equalMap.toString());

            for (it = 0; it < size; it++) {
                HashMap<String, Object> quesMap = new HashMap<String, Object>();
                conMap = conTemplList.get(it);
                conTemplStr = (String) conMap.get("templVersionid");
                String templType = (String) conMap.get("templType");
                if (!Constants.QUESTIONNAIRE_TYPE_0.equals(templType)) {
                    //暂时数据修改20180117
                    if (Constants.QUESTIONNAIRE_TYPE_5.equals(templType) || null != equalMap.get(conTemplStr)) {
                        // 该问卷与门诊问卷内容相同，需要剔除
                        logger.warn("erase templVersionId==" + conTemplStr);
                        continue;
                    }
                }
                // 此处后续需要使用redis缓存
                templMap.put("id", conTemplStr);
                List<ContentTemplVersion> ctvList = contentTemplDao.selectContentTemplNoTextById(templMap);
                if (null == ctvList || 0 == ctvList.size()) {
                    continue;
                }
                ContentTemplVersion ctVo = ctvList.get(0);
                templMap.put("id", ctVo.getTemplId());
                List<ContentTempl> ctList = contentTemplDao.selectTemplById(templMap);
                if (null == ctList || 0 == ctList.size()) {
                    continue;
                }
                ContentTempl conVo = ctList.get(0);
                quesMap.put("questionnaireId", conTemplStr);
                quesMap.put("questionnaireName", conVo.getTemplName());

                retList.add(quesMap);
            }
        }
        retOut.put("total", retList.size());
        retOut.put("rows", retList);

        return retOut;
    }

    // 患者专科袋详情查询接口实现
    public HashMap<String, Object> qryPatientContentDetail(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        HashMap<String, Object> retOut = new HashMap<String, Object>();

        String conTemplVerId = (String) argMap.get("conTemplVerId");
        String ptSchemeId = (String) argMap.get("ptSchemeId");
        String tenantId = (String) argMap.get("tenantId");
        String patientId = (String) argMap.get("patientId");
        String queueId = (String) argMap.get("queueId");
        HashMap<String, Object> templMap = new HashMap<String, Object>();
        // 此处后续需要使用redis缓存
        templMap.put("id", conTemplVerId);
        List<ContentTemplVersion> ctvList = contentTemplDao.selectContentTemplById(templMap);
        if (null == ctvList || 0 == ctvList.size()) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST, "任务内容模板版本为空！");
        }
        ContentTemplVersion ctVo = ctvList.get(0);
        JSONArray templJsonArray = JSON.parseArray(ctVo.getTemplData());
        //脑卒中队列模板内容去除症状内容
        if (queueId.contains("naocuzhong")){
            List<JSONObject> collect = templJsonArray.stream().map(item -> (JSONObject) item).filter(item -> !item.get("label").equals("体征")).collect(Collectors.toList());
            templJsonArray = JSON.parseArray(JSON.toJSONString(collect));
        }
        retOut.put("questionnaireData", templJsonArray);

        argMap.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 暂时只展示门诊任务
        List<HashMap<String, Object>> retList = patientTaskDao.selectTaskByPtSchemeIdAndTempl(argMap);
        if (null == ctvList || 0 == ctvList.size()) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_TASK_NOT_EXIST, "患者下无此任务相关内容！");
        }
        int it = 0;
        for (it = 0; it < retList.size(); it++) {
            HashMap<String, Object> taskInfoMap = retList.get(it);
            HashMap<String, Object> quesInputMap = new HashMap<String, Object>();
            // 先根据taskId+templType查询问卷答案，若无答案，则根据taskId查询问卷答案记录
            quesInputMap.put("taskId", taskInfoMap.get("taskId"));
            quesInputMap.put("contDataTemplType", taskInfoMap.get("templType"));
            List<PatientContentData> ptTaskConList = patientTaskConDao.selectContentDataByTaskId(quesInputMap);
            if (CollectionUtils.isEmpty(ptTaskConList)) {
                quesInputMap.put("contDataTemplType", null);
                ptTaskConList = patientTaskConDao.selectContentDataByTaskId(quesInputMap);
            }
            HashMap<String, Object> quesOutMap = new HashMap<String, Object>();
            if (!CollectionUtils.isEmpty(ptTaskConList)) {
                int k = 0;
                for (; k < ptTaskConList.size(); k++) {
                    PatientContentData pcdVo = ptTaskConList.get(k);
                    quesOutMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                }
            }
            taskInfoMap.put("values", quesOutMap);
        }
        // 生物样本收集（安医大需求）
        Map<String, Object> sampleMapIn = new HashMap<String, Object>();
        sampleMapIn.put("userId", patientId);
        sampleMapIn.put("ptSchemeId", ptSchemeId);
        sampleMapIn.put("tenantId", tenantId);
        List<Map<String, Object>> sampleList = this.listSampleInfo(sampleMapIn);
        if (!CollectionUtils.isEmpty(sampleList)) {
            retOut.put("sampleList", sampleList);
        }

        //重新排序这些随访任务。
        Collections.sort(retList, new TaskComparator());

        retOut.put("tasks", retList);

        return retOut;
    }

    // 患者操作记录查询接口实现
    public HashMap<String, Object> qryPatientOperationList(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        String flag = (String) argMap.get("flag");
        String tenantId = (String) argMap.get("tenantId");
        boolean appInvokeFlag = false;// app调用标志
        if (!StringUtils.isEmpty((String) argMap.get("invokeType"))) {
            // app侧调用无租户id等信息
            appInvokeFlag = true;
            argMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
        }
        String appTenantId = (String) argMap.get("appTenantId");

        int total = 0;
        HashMap<String, Object> retMap = new HashMap<String, Object>();
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        retMap.put("total", 0);
        retMap.put("rows", pqsList);

        // 若有服务号码或患者姓名，则先获取患者id串（可能有多个）
        List<String> userIdArray = new ArrayList<String>();
        int qryUserFlag = 0;
        String phoneNo = (String) argMap.get("phoneNo");
        String userName = (String) argMap.get("userName");// 可以是姓氏或姓名
        String patientId = (String) argMap.get("patientId");
        HashMap<String, Object> qryUserMap = new HashMap<String, Object>();
        if (null != phoneNo && !"".equals(phoneNo)) {
            qryUserMap.put("phoneNo", phoneNo);
            qryUserFlag = 1;
        }
        if (!StringUtils.isEmpty(patientId)) {
            qryUserMap.put("userId", patientId);
            qryUserFlag = 1;
        }
        if (null != userName && !"".equals(userName)) {
            argMap.put("userName", userName + "%");
        }
        if (1 == qryUserFlag) {
            if (appInvokeFlag) {
                qryUserMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
            } else {
                qryUserMap.put("tenantId", tenantId);
            }
            List<Patient> ptList = patientDao.select(qryUserMap);
            if (null == ptList || 0 == ptList.size()) {
                logger.warn("无此患者信息...arg==" + qryUserMap.toString());
                return retMap;
            }
            int ipt = 0;
            for (; ipt < ptList.size(); ipt++) {
                Patient ptVo = ptList.get(ipt);
                // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                userIdArray.add(ptVo.getId());
            }
        }

        // 根据当前登录账号获取，其可以查看的队列id（权限处理比较复杂，这里先简化）
        String authorId = (String) argMap.get("authorId");
        HashMap<String, Object> qryQueueMap = new HashMap<String, Object>();
        qryQueueMap.put("authorId", authorId);
        qryQueueMap.put("queueStatus", Constants.QUEUE_STATUS_NOMAL);// 队列状态正常
        qryQueueMap.put("tenantId", tenantId);
        qryQueueMap.put("queueTypePrivate", Constants.QUEUE_TYPE_PRIVATE);
        qryQueueMap.put("queueTypeTenant", Constants.QUEUE_TYPE_TENANT);
        qryQueueMap.put("queueTypePublic", Constants.QUEUE_TYPE_PUBLIC);

        List<FollowQueue> fqList = null;
        // 1：如果传入队列 则直接用队列查询 2：没有传入队列ID 则根据权限先查询 该用户有哪些队列权限 再查询
        String queueId = (String) argMap.get("queueId");
        if (appInvokeFlag) {
            if (!StringUtils.isBlank(queueId)) {
                Map<String, Object> queueMap = new HashMap<String, Object>();
                queueMap.put("id", queueId);
                fqList = queueDao.selectById(queueMap);
            }
        } else if (!StringUtils.isBlank(queueId)) {
            Map<String, Object> queueMap = new HashMap<String, Object>();
            queueMap.put("id", queueId);
            fqList = queueDao.selectById(queueMap);
        } else {
            fqList = queueDao.selectQueueIdByAuthority(qryQueueMap);
        }

        if (CollectionUtils.isEmpty(fqList)) {
            if (!appInvokeFlag) {
                logger.warn("该账号无可查看到的队列信息...arg==" + qryQueueMap.toString());
                return retMap;
            } else {
                logger.warn("该账号无可查看到的队列信息...app侧调用...");
            }
        } else {
            List<String> queueIdArray = new ArrayList<String>();
            int fqt = 0;
            for (; fqt < fqList.size(); fqt++) {
                FollowQueue fqVo = fqList.get(fqt);
                // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                queueIdArray.add(fqVo.getId());
            }

            // 获取随访患者list
            argMap.put("queueIdIn", queueIdArray);
        }
        if (0 != userIdArray.size()) {
            argMap.put("userIdIn", userIdArray);
        }
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            // 今日门诊记录flag=0（直接查询ia_operation_record.op_type=2|op_code=1000/1001）
            if ("0".equals(flag)) {
                int schemeBusiType = 0;
                if (paramMap.get("schemeBusiType") != null) {
                    schemeBusiType = (int) paramMap.get("schemeBusiType");
                }
                List<String> opCodeArr = new ArrayList<String>();
                opCodeArr.add(Constants.OP_CODE_1000);// 门诊建档
                opCodeArr.add(Constants.OP_CODE_1001);// 门诊随访录入
                argMap.put("opCodeArr", opCodeArr);
                argMap.put("opType", Constants.OP_TYPE_DOOR);
                argMap.put("currDay", DateUtil.getCurrDate());
                argMap.put("start", argMap.get("start"));
                argMap.put("end", argMap.get("end"));
                argMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
                if (Constants.SCHEME_BUSI_TYPE_2 == schemeBusiType) {
                    total = patientOperationRecordDao.countCompleteDoorTodayAll(argMap);
                } else {
                    total = patientOperationRecordDao.countCompleteDoorToday(argMap);
                }
                if (0 != total) {
                    if (Constants.SCHEME_BUSI_TYPE_2 == schemeBusiType) {
                        pqsList = patientOperationRecordDao.selectCompleteDoorTodayAll(argMap);
                    } else {
                        pqsList = patientOperationRecordDao.selectCompleteDoorToday(argMap);
                    }
                    if (CollectionUtils.isEmpty(pqsList)) {
                        total = 0;
                    } else {
                        int size = pqsList.size();
                        int kk = 0;
                        String pqsQueueId = "";
                        Map<String, Object> qryMapIn = new HashMap<String, Object>();
                        Map<String, Object> qryMapOut = new HashMap<String, Object>();
                        for (kk = 0; kk < size; kk++) {
                            Map<String, Object> pqsMap = pqsList.get(kk);
                            // 获取队列名称
                            pqsQueueId = (String) pqsMap.get("followQueueId");
                            qryMapIn.clear();
                            qryMapIn.put("queueId", pqsQueueId);
                            qryMapOut = getQueueName(qryMapIn, jedis);
                            pqsMap.put("followQueueName", qryMapOut.get("queueName"));
                        }
                    }
                }
            } else if ("1".equals(flag)) {
                // 线上主诉登记记录flag=1（直接查询ia_operation_record.op_type=1 &&
                // op_code=1009）
                jedis.select(Constants.REDIS_DB_INDEX_CONFIG);
                // 安医大特殊处理（门诊记录也要能展示在app上）
                if (StringUtils.isNotBlank(appTenantId) && Constants.TENANT_ID_FOR_AYD_MAS.equals(appTenantId)) {
                    // app上传
                    argMap.put("opType", Constants.OP_TYPE_SELF);
                    argMap.put("opCode", Constants.OP_CODE_1009);
                    // 门诊上传
                    argMap.put("opTypeDoor", Constants.OP_TYPE_DOOR);
                    argMap.put("opCodeDoor", Constants.OP_CODE_1001);
                    argMap.put("start", argMap.get("start"));
                    argMap.put("end", argMap.get("end"));
                    argMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
                    argMap.put("revSeqNo", Constants.TASK_SEQ_FOR_INIT);// 去除建档任务
                    total = patientOperationRecordDao.countIaOperateByUnion(argMap);
                    if (0 != total) {
                        pqsList = patientOperationRecordDao.listIaOperateByUnion(argMap);
                        if (CollectionUtils.isEmpty(pqsList)) {
                            total = 0;
                        } else {
                            int size = pqsList.size();
                            int kk = 0;
                            String pqsQueueId = "";
                            Map<String, Object> qryMapIn = new HashMap<String, Object>();
                            Map<String, Object> qryMapOut = new HashMap<String, Object>();
                            for (kk = 0; kk < size; kk++) {
                                Map<String, Object> pqsMap = pqsList.get(kk);
                                // 获取队列名称
                                pqsQueueId = (String) pqsMap.get("followQueueId");
                                qryMapIn.clear();
                                qryMapIn.put("queueId", pqsQueueId);
                                qryMapOut = getQueueName(qryMapIn, jedis);
                                pqsMap.put("followQueueName", qryMapOut.get("queueName"));
                                pqsMap.put("pregnancyWeek",
                                        ToolUtils.getPregnancyStr(Integer.parseInt("" + pqsMap.get("pregnancyDay"))));
                                pqsMap.put("age", ToolUtils.getAgeMonDayByBirthday(pqsMap.get("birthday").toString()));
                            }
                        }
                    }
                } else {
                    argMap.put("opType", Constants.OP_TYPE_SELF);
                    argMap.put("opCode", Constants.OP_CODE_1009);
                    argMap.put("start", argMap.get("start"));
                    argMap.put("end", argMap.get("end"));
                    argMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
                    total = patientOperationRecordDao.countIaOperate(argMap);
                    if (0 != total) {
                        pqsList = patientOperationRecordDao.listIaOperate(argMap);
                        if (CollectionUtils.isEmpty(pqsList)) {
                            total = 0;
                        } else {
                            int size = pqsList.size();
                            int kk = 0;
                            String pqsQueueId = "";
                            Map<String, Object> qryMapIn = new HashMap<String, Object>();
                            Map<String, Object> qryMapOut = new HashMap<String, Object>();
                            for (kk = 0; kk < size; kk++) {
                                Map<String, Object> pqsMap = pqsList.get(kk);
                                // 获取队列名称
                                pqsQueueId = (String) pqsMap.get("followQueueId");
                                qryMapIn.clear();
                                qryMapIn.put("queueId", pqsQueueId);
                                qryMapOut = getQueueName(qryMapIn, jedis);
                                pqsMap.put("followQueueName", qryMapOut.get("queueName"));
                                pqsMap.put("pregnancyWeek",
                                        ToolUtils.getPregnancyStr(Integer.parseInt("" + pqsMap.get("pregnancyDay"))));
                                pqsMap.put("age", ToolUtils.getAgeMonDayByBirthday(pqsMap.get("birthday").toString()));
                            }
                        }
                    }
                }
            }
        } catch (JedisConnectionException jex) {
            logger.error("redis连接异常..." + jex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
        } finally {
            if (null != jedis) {
                try {
                    jedis.close();
                    logger.warn("close redis connection...");
                } catch (Exception ex) {
                    ex.printStackTrace();
                    throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_CLOSE_FAILED,
                            "Redis缓存关闭失败!"));
                }
            }
        }

        retMap.put("total", total);
        retMap.put("rows", pqsList);

        return retMap;
    }

    @Override
    public Map<String, Object> qryPatientDetail(Map<String, Object> paramMap) throws Exception {
        String tenantId = (String) paramMap.get("tenantId");
        Map<String, Object> rspMap = new HashMap<String, Object>();
        // 查询患者基本信息
        Map<String, Object> qryUserMap = new HashMap<String, Object>();
        qryUserMap.put("userId", paramMap.get("userId"));
        qryUserMap.put("tenantId", tenantId);
        Patient pt = patientDao.selectById(qryUserMap);
        if (pt == null) {
            logger.warn("患者信息不存在...arg==" + qryUserMap.toString());
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "患者信息不存在");
        }

        // 查看患者所在队列 状态正常和 待审核记录
        Map<String, Object> qryPqsMap = new HashMap<String, Object>();
        qryPqsMap.put("userId", paramMap.get("userId"));
        List<String> statulist = new ArrayList<String>();// 查询出待审核和正常
        // 两个状态的队列患者实例记录

        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT);
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        qryPqsMap.put("status", statulist);
        List<PatientQueueScheme> pqsList = patientQueueSchemeDao.selectByUserId(qryPqsMap);

        // 根据当前登录账号获取，其可以查看的队列id
        String authorId = (String) paramMap.get("authorId");
        Map<String, Object> qryQueueMap = new HashMap<String, Object>();
        qryQueueMap.put("authorId", authorId);
        qryQueueMap.put("queueStatus", Constants.QUEUE_STATUS_NOMAL);// 队列状态正常
        qryQueueMap.put("tenantId", tenantId);
        qryQueueMap.put("queueTypePrivate", Constants.QUEUE_TYPE_PRIVATE);
        qryQueueMap.put("queueTypeTenant", Constants.QUEUE_TYPE_TENANT);
        qryQueueMap.put("queueTypePublic", Constants.QUEUE_TYPE_PUBLIC);

        List<FollowQueue> fqList = null;
        // 则根据权限先查询 该用户有哪些队列权限
        fqList = queueDao.selectQueueIdByAuthority(qryQueueMap);
        if (null == fqList || 0 == fqList.size()) {
            logger.warn("该账号无可查看到的队列信息...arg==" + qryQueueMap.toString());
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_HAS_NO_QUEUE_AUTHORITY, "该账号无可查看到的队列信息");
        }

        List<Map<String, Object>> queueList = new ArrayList<Map<String, Object>>();
        Map<String, Object> map = null;
        for (int i = 0; i < pqsList.size(); i++) {
            String queueId = pqsList.get(i).getQueueId();
            for (int j = 0; j < fqList.size(); j++) {
                if (queueId.equals(fqList.get(j).getId())) {// 如果有权限看该队列
                    // 则将队列加入返回患者队列list中
                    map = new HashMap<String, Object>();
                    map.put("queueId", fqList.get(j).getId());
                    map.put("queueName", fqList.get(j).getQueueName());
                    map.put("queuePatientStatus", pqsList.get(i).getUserStatus());
                    queueList.add(map);
                }
            }
        }
        rspMap.put("queues", queueList);
        rspMap.put("phoneNum", pt.getPhoneNo());
        rspMap.put("pregnancyDay", pt.getPregnancyDay());
        rspMap.put("userName", pt.getUserName());
        rspMap.put("userType", pt.getUserType());
        rspMap.put("createTime", pt.getCreateTime());

        if (pt.getPregnancyDay() > 0) {
            long correctAge = ToolUtils.getCorrect(pt.getBirthday(), pt.getPregnancyDay());
            Date date = new Date(correctAge);
            String pregnancyWeek = ToolUtils.getPregnancyStr(pt.getPregnancyDay());
            rspMap.put("age", ToolUtils.getAgeByBirthday(DateUtil.getDate_8(date)));
            rspMap.put("pregnancyWeek", pregnancyWeek);
        }
        // 如果患者是母亲类型 判断是否分娩 已分娩需返回宝宝信息
        return rspMap;
    }

    // 医生主页 患者统计信息接口实现
    @Override
    public Map<String, Object> qryPatientStatistics(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> retMap = new HashMap<String, Object>();
        String tenantId = (String) paramMap.get("tenantId");

        List<String> queueIdArray = followQueueService.getQueueArrByAuthority(paramMap);
        if (CollectionUtils.isEmpty(queueIdArray)) {
            logger.info("该用户无可查看的队列|患者");
            retMap.put("patientTotal", 0);
            retMap.put("activeWeek", 0);
            retMap.put("activeWeekService", 0);
            retMap.put("patientAddWeek", 0);
            return retMap;
        }

        paramMap.put("queueIdIn", queueIdArray);
        paramMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户

        // 患者总数
        int patientTotal = patientQueueSchemeDao.countTotalPtQueueNumByCondition(paramMap);// 患者同时加入多个队列
        // 会查出重复患者
        String[] weeks = DateUtil.getWeekStartEnd();
        // 本周新增患者总数
        paramMap.put("qryStartTime", weeks[0]);
        paramMap.put("qryEndTime", weeks[1]);
        // 患者同时加入多个队列会查出重复患者
        int patientAddWeek = patientQueueSchemeDao.countTotalPtQueueNumByCondition(paramMap);

        // 本周活跃
        Map<String, Object> qryWeekActiveMap = new HashMap<String, Object>();
        qryWeekActiveMap.put("queueIdIn", queueIdArray);
        qryWeekActiveMap.put("startTime", weeks[0]);
        qryWeekActiveMap.put("endTime", weeks[1]);
        // 活跃类型 暂时只统计患者主页选项卡中
        qryWeekActiveMap.put("busiCategorys", paramMap.get("busiCategorys"));
        qryWeekActiveMap.put("testbusiCategorys", paramMap.get("testbusiCategorys"));
        qryWeekActiveMap.put("tenantId", tenantId);
        qryWeekActiveMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        int activeWeek = patientOperationRecordDao.CountActivePatientByWeek(qryWeekActiveMap);

        int activeWeekService = 0;// 本周服务先不统计
        /*
         * Map<String, Object> qryWeekServicesMap = new HashMap<String,
         * Object>(); qryWeekServicesMap.put("deptId", paramMap.get("deptId"));
         * qryWeekServicesMap.put("startTime", weeks[0]);
         * qryWeekServicesMap.put("endTime", weeks[1]); int
         * activeWeekonlineService =
         * serviceManagerDao.weekCountOnlineServiceTimesByDeptId(
         * qryWeekServicesMap); int activeWeekDataReadService =
         * serviceManagerDao.weekCountdataReadServiceTimesByDeptId(
         * qryWeekServicesMap); activeWeekService = activeWeekonlineService +
         * activeWeekDataReadService;
         */
        // patientOperationRecordDao.CountByConditon(map);
        retMap.put("patientTotal", patientTotal);
        retMap.put("activeWeek", activeWeek);
        retMap.put("activeWeekService", activeWeekService);
        retMap.put("patientAddWeek", patientAddWeek);

        return retMap;
    }

    // 获取患者已过期未处理的任务list接口实现
    public List<PatientTask> getPatientExpieredTaskList(Map<String, Object> servParamMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(servParamMap);
        List<PatientTask> ptExpList = patientTaskDao.selectExpiredTask(argMap);
        return ptExpList;
    }

    // 获取失访需要结案的任务
    public List<PatientTask> selectCloseTask(Map<String, Object> servParamMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(servParamMap);
        List<PatientTask> ptExpList = patientTaskDao.selectCloseTask(argMap);
        return ptExpList;
    }

    // 处理患者已过期未处理的任务接口实现
    @Transactional
    public void dealPatientExpieredTask(Map<String, Object> servParamMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(servParamMap);
        logger.warn("dealPatientExpieredTask input==" + argMap.toString());

        String taskId = (String) argMap.get("taskId");
        String ptSchemeId = (String) argMap.get("ptSchemeId");
        String authorId = (String) argMap.get("authorId");
        String updateTime = (String) argMap.get("updateTime");
        String updateAccept = (String) argMap.get("updateAccept");
        String userId = (String) argMap.get("userId");
        String opCode = (String) argMap.get("opCode");
        String queueId = (String) argMap.get("queueId");
        String taskName = (String) argMap.get("taskName");
        String taskType = (String) argMap.get("taskType");

        HashMap<String, Object> taskMap = new HashMap<String, Object>();
        // 先锁表，防止并发更新
        taskMap.put("updateAuthor", authorId);
        taskMap.put("updateTime", updateTime);
        taskMap.put("updateAccept", updateAccept);
        taskMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        taskMap.put("taskId", taskId);
        int upret = patientTaskDao.updatePatientTaskById(taskMap);
        if (0 == upret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_TASK_NOT_EXIST, "患者当前任务不存在！"));
        }

        // 队列信息校验
        HashMap<String, Object> queueInMap = new HashMap<String, Object>();
        queueInMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueInMap);
        if (null == queueList || 0 == queueList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }

        // pt_task_info状态更新为2
        List<PatientTask> ptList = patientTaskDao.selectById(taskMap);
        if (null == ptList || 0 == ptList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_TASK_NOT_EXIST, "患者当前任务不存在！"));
        }
        PatientTask ptask = ptList.get(0);
        String taskStatus = ptask.getTaskStatus();
        if (!Constants.PATIENT_TASK_STATUS_INIT.equals(taskStatus)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_TASKSTATUS_NOT_INIT,
                    "患者任务状态非未随访，无法更新为过期任务！"));
        }

        taskMap.put("taskStatus", Constants.PATIENT_TASK_STATUS_EXPIRED);
        taskMap.put("updateAuthor", authorId);
        taskMap.put("updateTime", updateTime);
        taskMap.put("updateAccept", updateAccept);
        taskMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        upret = patientTaskDao.updatePatientTaskById(taskMap);
        if (0 == upret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_TASK_NOT_EXIST, "患者当前任务不存在！"));
        }
        // pt_task_info_his历史轨迹变化记录
        patientTaskDao.insertPatientTaskHisById(taskMap);

        // pt_queuescheme_info更新及历史轨迹变化记录
        HashMap<String, Object> queueMap = new HashMap<String, Object>();
        queueMap.put("updateAuthor", authorId);
        queueMap.put("updateTime", updateTime);
        queueMap.put("updateAccept", updateAccept);
        queueMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        queueMap.put("id", ptSchemeId);
        if (Constants.TASK_TYPE_SCHEME_TEMP.equals(taskType)) {
            // 线上随访
            queueMap.put("onlineLostIncr", "1");
        } else {
            // 门诊随访
            queueMap.put("lostNumFlag", "1");
        }
        queueMap.put("updateAuthor", authorId);
        upret = patientQueueSchemeDao.updatePtQueueSchemeRecord(queueMap);
        if (0 == upret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_NOT_EXIST, "患者队列实例无记录！"));
        }
        patientQueueSchemeDao.insertPatientQueueSchemeHis(queueMap);

        // 入失访记录表pt_lost_rd，先查询是否已经有记录
        Map<String, Object> lostMapIn = new HashMap<String, Object>();
        lostMapIn.put("taskId", taskId);
        List<PtLostRd> ptlostList = patientTaskDao.selectPatientLostByTaskId(lostMapIn);
        if (!CollectionUtils.isEmpty(ptlostList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_LOSTRD_ALREADY_EXIST,
                    "失访记录已经存在，禁止重复处理！"));
        }
        PtLostRd prdVo = new PtLostRd();
        prdVo.setAuthorId(authorId);
        prdVo.setCreateTime(updateTime);
        prdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_LOST_ID));
        prdVo.setLostDate(DateUtil.getCurrDate());
        prdVo.setPtSchemeid(ptask.getPtSchemeid());
        prdVo.setQueueId(queueId);
        prdVo.setReasonId("");
        prdVo.setTaskId(taskId);
        prdVo.setTaskName(ptask.getTaskName());
        prdVo.setUpdateAccept(updateAccept);
        prdVo.setUpdateTime(updateTime);
        prdVo.setUserId(userId);
        patientTaskDao.savePatientLostInfo(prdVo);

        // 操作日志记录（ia_operation_record）
        Map<String, Object> ptInMap = new HashMap<String, Object>();
        ptInMap.put("userId", userId);
        ptInMap.put("tenantId", queueList.get(0).getTenantId());
        Patient ptOut = patientDao.selectById(ptInMap);
        if (null == ptOut) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
        }

        /**
         * 任务失访并且为随访期最后一个节点
         * 也就是该患者随访任务结束，结案了
         * 入fu_closecase_record结案记录表
         */
        if (PropertiesUtils.getProperty("isCloseTask").equals("true")) {
            if (ptask.getNextTaskId() == null && DateUtil.daysBetweenDateStr(ptask.getEndTime(), DateUtil.getCurrDate2()) <= 0) {
                FuClosecaseRecord temp = new FuClosecaseRecord();
                temp.setId(SeqUtil.getSeqNo());
                temp.setUserId(ptOut.getId());
                temp.setUserName(ptOut.getUserName());
                temp.setPhone(ptOut.getPhoneNo());
                temp.setGender(ptOut.getGender());
                temp.setBirthdate(DateUtil.getDate(ptOut.getBirthday()));
                temp.setCloseType(Constants.FOLLOWUP_OVER);//手动中止
                temp.setTenantId(ptOut.getTenantId());
                temp.setCloseReason("随访期结束");
                temp.setCreateTime(new Date());
                temp.setQueueId(queueId);
                temp.setTaskId(taskId);
                temp.setCreater(authorId);
                temp.setPtSchemeid(ptSchemeId);
                fuClosecaseRecordDao.insert(temp);
            }
        }

        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", ptOut.getUserName());
        paramRecord.put("userId", userId);
        paramRecord.put("queueId", queueId);
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_21);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_BG_ADMIN);
        paramRecord.put("authorName", "");
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", "");
        paramRecord.put("remark", "后台更新患者【" + ptOut.getUserName() + "】过期未完成任务【" + taskName + "】为失访状态");
        paramRecord.put("opType", argMap.get("opType"));
        paramRecord.put("taskId", taskId);
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        return;
    }

    // 根据用户id+患者队列实例id查询患者信息接口实现
    @Override
    public Map<String, Object> getPatientInfoByUserIdAndPtSchemeId(Map<String, Object> paramMap) throws Exception {
        String patientId = (String) paramMap.get("patientId");
        String ptSchemeId = (String) paramMap.get("ptSchemeId");
        String tenantId = (String) paramMap.get("tenantId");


        Map<String, Object> ptMap = new HashMap<String, Object>();
        ptMap.put("userId", patientId);
        ptMap.put("tenantId", tenantId);
        Patient pt = patientDao.selectById(ptMap);
        if (null == pt || StringUtils.isEmpty(pt.getId())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
        }
        List<String> userStatusList = new ArrayList<String>();
        Map<String, Object> ptQsMap = new HashMap<String, Object>();
        ptQsMap.put("id", ptSchemeId);
        userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_ADVANCE);
        // userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT);
        ptQsMap.put("userStatusIn", userStatusList);
        List<PatientQueueScheme> ptQsList = patientQueueSchemeDao.selectPatientByCondition(ptQsMap);
        if (null == ptQsList || 0 == ptQsList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_NOT_EXIST,
                    "根据患者队列实例id查询患者队列实例表记录不存在！"));
        }

        //获取 高危信息管理 任务里面的几类高危儿 [sf_gwefl_I,sf_gwefl_II,sf_gwefl_III]
        List<String> gwList = Arrays.asList("sf_gwefl_I", "sf_gwefl_II", "sf_gwefl_III");

        HashMap<String, Object> mapCon = new HashMap<>();
        mapCon.put("taskFlag", "1");
        mapCon.put("ptSchemeId", ptSchemeId);
        List<PatientTask> patientTasks = patientTaskDao.selectByPtSchemeId(mapCon);
        List<PatientTask> taskList = patientTasks.stream().filter(patientTask -> patientTask.getTaskName().contains("高危信息管理")).collect(Collectors.toList());

        String gwSign = "";
        if (taskList.size() > 0) {
            PatientTask patientTask = taskList.get(0);
            mapCon.clear();
            mapCon.put("taskId", patientTask.getId());
            List<PatientContentData> contentData = patientTaskContentDAO.selectContentDataByTaskId(mapCon);
            if (contentData.size() > 0) {
                List<PatientContentData> collect = contentData.stream().filter(data -> gwList.contains(data.getQuestionId())).collect(Collectors.toList());
                if (collect.size() > 0) {
                    for (PatientContentData patientContentData : collect) {
                        List<String> list = Arrays.asList(patientContentData.getQuestionAnswer().replaceAll("\"", "").replace("[", "").replace("]", "").split(","));
                        if (list.size() > 0 && !list.contains("无")) {
                            if (patientContentData.getQuestionId().equals("sf_gwefl_III")) {
                                gwSign = "III类";
                                break;
                            } else if (patientContentData.getQuestionId().equals("sf_gwefl_II")) {
                                gwSign = "II类";
                                continue;
                            }
                            if (patientContentData.getQuestionId().equals("sf_gwefl_I")) {
                                gwSign = "I类";
                                continue;
                            }
                        }
                    }
                }
            }
        }
        PatientQueueScheme ptqsVo = ptQsList.get(0);
        Map<String, Object> queueMap = new HashMap<String, Object>();
        queueMap.put("id", ptqsVo.getQueueId());
        List<FollowQueue> queueList = queueDao.selectById(queueMap);
        if (null == queueList || 0 == queueList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "根据队列id查询队列表记录不存在！"));
        }
        FollowQueue fqVo = queueList.get(0);
        Map<String, Object> queueInfo = new HashMap<String, Object>();
        queueInfo.put("queueName", fqVo.getQueueName());
        queueInfo.put("queueId", fqVo.getId());
        queueInfo.put("pregnancyWeekStr", ToolUtils.getPregnancyStr(pt.getPregnancyDay()));
        queueInfo.put("ageMonDayStr", ToolUtils.getAgeMonDayByBirthday(pt.getBirthday()));
        queueInfo.put("ptSchemeId", ptSchemeId);

        Map<String, Object> outRet = new HashMap<String, Object>();
        outRet.put("PatientInfo", pt);
        outRet.put("gwSign", gwSign);
        outRet.put("QueueSchemeInfo", queueInfo);

        return outRet;
    }

    // 根据门诊号查询患者信息
    public List<Map<String, Object>> getPatientInfoByOutNo(Map<String, Object> paramMap) throws Exception {
        List<Map<String, Object>> ptList = patientDao.selectDataByOutNo(paramMap);
        return ptList;
    }

    // 根据门诊号更新患者信息
    @Transactional
    public void modPatientInfoByOutNo(Map<String, Object> argMap) throws Exception {
        patientDao.modDataByOutNo(argMap);
        return;
    }

    // 数据中心随访患者信息查询接口实现
    public HashMap<String, Object> qryPatientListDataCenter(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        String tenantId = (String) argMap.get("tenantId");
        int total = 0;
        HashMap<String, Object> retMap = new HashMap<String, Object>();
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        retMap.put("total", 0);
        retMap.put("rows", pqsList);

        // 若有服务号码或患者姓名，则先获取患者id串（可能有多个）
        List<String> userIdArray = new ArrayList<String>();
        int qryUserFlag = 0;
        String phoneNo = (String) argMap.get("phoneNo");
        String userName = (String) argMap.get("userName");// 可以是姓氏或姓名
        HashMap<String, Object> qryUserMap = new HashMap<String, Object>();
        if (null != phoneNo && !"".equals(phoneNo)) {
            qryUserMap.put("phoneNo", phoneNo);
            qryUserFlag = 1;
        }
        if (null != userName && !"".equals(userName)) {
            argMap.put("userName", userName + "%");
        }
        if (1 == qryUserFlag) {
            List<Patient> ptList = patientDao.select(qryUserMap);
            if (null == ptList || 0 == ptList.size()) {
                return retMap;
            }
            int ipt = 0;
            for (; ipt < ptList.size(); ipt++) {
                Patient ptVo = ptList.get(ipt);
                // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                userIdArray.add(ptVo.getId());
            }
        }

        // 根据当前登录账号获取，其可以查看的队列id（权限处理比较复杂，这里先简化）
        String authorId = (String) argMap.get("authorId");
        HashMap<String, Object> qryQueueMap = new HashMap<String, Object>();
        qryQueueMap.put("authorId", authorId);
        qryQueueMap.put("queueStatus", Constants.QUEUE_STATUS_NOMAL);// 队列状态正常
        qryQueueMap.put("tenantId", tenantId);
        qryQueueMap.put("queueTypePrivate", Constants.QUEUE_TYPE_PRIVATE);
        qryQueueMap.put("queueTypeTenant", Constants.QUEUE_TYPE_TENANT);
        qryQueueMap.put("queueTypePublic", Constants.QUEUE_TYPE_PUBLIC);

        List<FollowQueue> fqList = null;
        // 1：如果传入队列 则直接用队列查询 2：没有传入队列ID 则根据权限先查询 该用户有哪些队列权限 再查询
        String queueId = (String) argMap.get("queueId");
        if (!StringUtils.isBlank(queueId)) {
            Map<String, Object> queueMap = new HashMap<String, Object>();
            queueMap.put("id", queueId);
            fqList = queueDao.selectById(queueMap);
        } else {
            List<Map<String, Object>> lists = IConfCacheDAO.selectAuthorId(qryQueueMap);
            if (lists != null && lists.size() > 0) {
                fqList = queueDao.selectQueueIdByparentId(qryQueueMap);
            } else {
                fqList = queueDao.selectQueueIdByAuthority(qryQueueMap);
                //根据authorId查询此用户拥有哪些队列的权限
                if (ObjectUtil.isNotEmpty(fqList)) {
                    List<String> queueIds = followQueueAuthorityDAO.getDuiLieByAuthorId(authorId);
                    fqList = fqList.stream().filter(item -> {
                        if (queueIds.contains(item.getId())) {
                            return true;
                        } else {
                            return false;
                        }
                    }).collect(Collectors.toList());
                }
            }
        }

        if (null == fqList || 0 == fqList.size()) {
            logger.warn("该账号无可查看到的队列信息...arg==" + qryQueueMap.toString());
            return retMap;
        }
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.select(Constants.REDIS_DB_INDEX_CONFIG);

            List<String> queueIdArray = new ArrayList<String>();
            int fqt = 0;
            for (; fqt < fqList.size(); fqt++) {
                FollowQueue fqVo = fqList.get(fqt);
                // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                queueIdArray.add(fqVo.getId());
            }

            // 获取随访患者list
            argMap.put("queueIdIn", queueIdArray);
            if (0 != userIdArray.size()) {
                argMap.put("userIdIn", userIdArray);
            }
            List<String> userStatusList = new ArrayList<String>();
            userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
            // userStatusList.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT);// 队列中待审核用户
            if (!argMap.containsKey("userStatus")) {
                argMap.put("userStatusIn", userStatusList);
            }

            total = patientQueueSchemeDao.countPatientDataCenter(argMap);
            if (total > 0) {
                pqsList = patientQueueSchemeDao.selectPatientDataCenter(argMap);
                if (null == pqsList || 0 == pqsList.size()) {
                    // 数据被删除或改变了
                    total = 0;
                } else {
                    int pq = 0;
                    String pqsQueueId = "";
                    Map<String, Object> qryMapIn = new HashMap<String, Object>();
                    Map<String, Object> qryMapOut = new HashMap<String, Object>();
                    for (; pq < pqsList.size(); pq++) {
                        Map<String, Object> pqsMap = pqsList.get(pq);

                        // 根据患者id查询对应的队列名称
                        Map<String, Object> map = patientQueueSchemeDao.selectListInfoByPatientId((String) pqsMap.get("patientId"));

                        // 获取队列名称
                        pqsQueueId = (String) pqsMap.get("followQueueId");
                        qryMapIn.clear();
                        qryMapIn.put("queueId", pqsQueueId);
                        qryMapOut = getQueueName(qryMapIn, jedis);
                        pqsMap.put("followQueueName", qryMapOut.get("queueName"));

                        // 获取方案名称
                        qryMapIn.clear();
                        qryMapIn.put("schemeId", (String) pqsMap.get("schemeId"));
                        qryMapOut = getSchemeName(qryMapIn, jedis);
                        pqsMap.put("schemeName", qryMapOut.get("schemeName"));
                        try {
                            pqsMap.put("age", ToolUtils.getAgeMonDayByBirthday("" + pqsMap.get("birthday")));
                        } catch (Exception e) {
                            pqsMap.put("age", "");
                        }

                        try {
                            pqsMap.put("pregnancyWeek",
                                    ToolUtils.getPregnancyStr(Integer.parseInt("" + pqsMap.get("pregnancyDay"))));
                        } catch (Exception e) {
                            pqsMap.put("pregnancyWeek", "");
                        }
                    }
                }
            }
        } catch (JedisConnectionException jex) {
            logger.error("redis连接异常..." + jex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
        } finally {
            if (null != jedis) {
                try {
                    jedis.close();
                    logger.warn("close redis connection...");
                } catch (Exception ex) {
                    ex.printStackTrace();
                    throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_CLOSE_FAILED,
                            "Redis缓存关闭失败!"));
                }
            }
        }

        retMap.put("total", total);
        retMap.put("rows", pqsList);

        return retMap;
    }

    // 扫码自助建档
    @Transactional
    public Map<String, Object> registerPatientForQrcode(Map<String, Object> servParamMap) throws Exception {
        logger.warn("registerPatientForQrcode arg==" + servParamMap.toString());
        List<Patient> ptList = new ArrayList<Patient>();// 用来存放用户信息给同步时候使用
        Map<String, Object> outRet = new HashMap<String, Object>();
        String queueId = (String) servParamMap.get("queueId");
        String deptId = (String) servParamMap.get("deptId");
        String defaultBabyQueueId = (String) servParamMap.get("defaultBabyQueueId");
        String userId = "";
        String ptSchemeId = "";
        Map<String, Object> map = null;
        Map<String, Object> mapSms = new HashMap<String, Object>();
        int syng = 0;

        // 队列信息校验
        HashMap<String, Object> queueInMap = new HashMap<String, Object>();
        queueInMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueInMap);
        if (null == queueList || 0 == queueList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }

        if (null != servParamMap.get("patient")) {
            Patient pt = (Patient) servParamMap.get("patient");
            map = registerPatientMethod(servParamMap, pt, queueId);
            ptList.add(syng, (Patient) map.get("patient"));
            userId = (String) map.get("userId");
            ptSchemeId = (String) map.get("ptSchemeId");
            outRet.put("patientId", userId);
            outRet.put("ptSchemeId", ptSchemeId);
            syng++;
        }

        @SuppressWarnings("unchecked")
        List<Patient> listbaby = (List<Patient>) servParamMap.get("listbaby");
        if (listbaby.size() <= 0) {
            if (null != servParamMap.get("patientBaby")) {
                Patient ptBaby = (Patient) servParamMap.get("patientBaby");
                if (!StringUtils.isBlank(userId)) { // 为空 在表示 只是添加宝宝
                    ptBaby.setRelevantId(userId);
                }
                map = registerPatientMethod(servParamMap, ptBaby, defaultBabyQueueId);
            }
            if (syng > 0) {
                ptList.add(syng, (Patient) map.get("patient"));
                syng++;
            } else {
                ptList.add(0, (Patient) map.get("patient"));
                syng++;
            }
            userId = (String) map.get("userId");
            ptSchemeId = (String) map.get("ptSchemeId");
            outRet.put("patientId", userId);
            outRet.put("ptSchemeId", ptSchemeId);
        } else {
            for (int i = 0; i < listbaby.size(); i++) {
                Patient ptBaby = (Patient) listbaby.get(i);
                if (!StringUtils.isBlank(userId)) { // 为空 在表示 只是添加宝宝
                    ptBaby.setRelevantId(userId);
                }
                map = registerPatientMethod(servParamMap, ptBaby, defaultBabyQueueId);
                if (syng > 0) {
                    ptList.add(syng, (Patient) map.get("patient"));
                    syng++;
                } else {
                    ptList.add(0, (Patient) map.get("patient"));
                    syng++;
                }
            }

        }
        // 发消息到 患者注册 消息队列topic 放在最后处理
        DepartmentBasic dept = null;
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("departmentId", deptId);// 随访科室ID
        paramMap.put("queueId", queueId);
        paramMap.put("queueName", map.get("queueName").toString());
        String appDeptId = "";
        if (!StringUtils.isBlank(deptId)) {
            map.clear();
            map.put("deptId", deptId);
            dept = deparmentBasicDao.selectAppDeptId(map);
            if (null != dept) {
                appDeptId = String.valueOf(dept.getRefDepartmentId());
                paramMap.put("refDepartmentId", appDeptId);// app科室ID
            }
        }

        for (int i = 0; i < ptList.size(); i++) {
            mapSms.put("deptId", deptId);
            mapSms.put("code", Constants.SMS_TEMPLATE_REGISTER_TYPE);
            // String smsContent =
            // bsSmsTemplateService.getSmsTemplateByCondition(mapSms);
            String smsContent = "";
            if (!Constants.QUEUE_PATIENT_REGISTER_NOT_SEND_SMS.equals(queueList.get(0).getSmsFlag())) {
                smsContent = bsSmsTemplateService.getSmsTemplateByCondition(map);
            }

        }
        return outRet;
    }

    private Map<String, Object> registerPatientMethod(Map<String, Object> servParamMap, Patient pt, String queueId)
            throws Exception {
        // boolean synch = false;
        String updateAcceptid = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_SYSTEMID);// 操作流水
        String updateTime = (String) servParamMap.get("updateTime");
        String updateAccept = (String) servParamMap.get("updateAccept");
        String authorName = (String) servParamMap.get("authorName");
        String opCode = (String) servParamMap.get("opCode");
        String opType = (String) servParamMap.get("opType");
        Map<String, Object> quesMap = (JSONObject) servParamMap.get("contentData");
        String phoneNo = pt.getPhoneNo();
        String tenantId = (String) servParamMap.get("tenantId");
        String wechat_id = (String) servParamMap.get("wechat_id");
        String sourceType = (String) servParamMap.get("sourceType");
        // 队列信息校验
        HashMap<String, Object> queueMap = new HashMap<String, Object>();
        queueMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueMap);
        if (null == queueList || 0 == queueList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }

        FollowQueue fq = (FollowQueue) queueList.get(0);
        if (!Constants.QUEUE_STATUS_NOMAL.equals(fq.getQueueStatus())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_STATUS_IRREGULAR, "当前加入的队列状态不正常，无法添加患者！"));
        }
        /*
         * 租户id必须存在，一个用户加入某个租户下的队列，则记录一份用户信息， 同时记录一份基本用户信息， 基本用户信息tenant_id=0
         * add by DemonLee, 2017.6.11
         */
        if (StringUtils.isEmpty(tenantId)) {
            // session中没有，则从队列下获取，队列下没有，则报错
            tenantId = fq.getTenantId();
            if (StringUtils.isEmpty(tenantId)) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_FOR_TENANT_NOT_EXIST,
                        "租户id为空或未配置，无法添加患者！"));
            }
        }

        int targetNum = fq.getTargetNum();// 队列目标人数
        int currNum = fq.getCurrNum();// 队列当前人数
        if (Constants.QUEUE_TARGET_NUM_INFINITE == targetNum) {
            // -1表示不设上限，可以任意添加患者
        } else if (targetNum <= 0) {
            // 其他小于等于0的数不合理，异常退出
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_TARGETNUM_CONFIG_ERROR,
                    "当前队列【" + fq.getQueueName() + "】目标人数配置错误，无法添加新患者！"));
        } else if (currNum >= targetNum) {
            // 当前人数已达到目标人数，无法继续添加患者
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_TARGETNUM_LIMIT,
                    "当前队列【" + fq.getQueueName() + "】人数已达到上限，无法添加新患者！"));
        }

        // 校验账户信息
        String ptAccountId = "";// 账号id
        String authorId = "APP患者自主";
        HashMap<String, Object> qryPtMap = new HashMap<String, Object>();
        qryPtMap.put("phoneNo", phoneNo);
        List<PtAccountInfo> ptAcList = ptAccountDao.selectPtAccountByPhoneNo(qryPtMap);
        if (null != ptAcList && 0 != ptAcList.size()) {
            PtAccountInfo ptAcVo = ptAcList.get(0);
            ptAccountId = ptAcVo.getId();
        } else {
            ptAccountId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_ACCOUNTID);
            PtAccountInfo ptAcVo = new PtAccountInfo();
            ptAcVo.setAccountName(pt.getUserName());//
            ptAcVo.setAuthorId(authorId);
            ptAcVo.setCreateTime(updateTime);
            ptAcVo.setId(ptAccountId);
            ptAcVo.setPhoneNo(phoneNo);
            ptAcVo.setRemark("建档新增");
            ptAcVo.setUpdateTime(updateTime);
            ptAccountDao.savePatientAccountInfo(ptAcVo);
        }

        // 校验患者信息（是否已经建档）
        qryPtMap.clear();
        qryPtMap.put("phoneNo", phoneNo);
        qryPtMap.put("userName", pt.getUserName());
        qryPtMap.put("wechat_id", wechat_id);
        qryPtMap.put("tenantId", tenantId);
        List<Patient> ptList = patientDao.selectByPhoneNo(qryPtMap);
        String userId = "";
        int redisFlag = 0;
        if (CollectionUtils.isEmpty(ptList)) {
            // 用基本租户再查
            int userExistFlag = 0;
            qryPtMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
            ptList = patientDao.selectByPhoneNo(qryPtMap);
            if (!CollectionUtils.isEmpty(ptList)) {
                userId = ptList.get(0).getId();
                userExistFlag = 1;
            } else {
                userId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_USERID);
            }
            // 入患者信息表pt_user_info
            pt.setId(userId);
            pt.setAccountId(ptAccountId);
            pt.setCreateAuthor("用户app");
            if (0 == userExistFlag) {
                pt.setTenantId(Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
                patientDao.savePatientInfo(pt);
            }
            pt.setTenantId(tenantId);
            patientDao.savePatientInfo(pt);

            // 历史表
            Map<String, Object> userHisMap = new HashMap<String, Object>();
            userHisMap.put("userId", userId);
            userHisMap.put("updateTime", updateTime);
            userHisMap.put("updateType", Constants.UPDATE_TYPE_INSERT);
            userHisMap.put("updateAccept", updateAccept);
            userHisMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
            patientDao.savePatientHisInfo(userHisMap);
            userHisMap.put("tenantId", tenantId);
            patientDao.savePatientHisInfo(userHisMap);

            redisFlag = 1;
            // synch = true;
        } else {
            pt = ptList.get(0);
            userId = pt.getId();
            qryPtMap.put("userId", userId);
            qryPtMap.put("phoneNo", phoneNo);
            qryPtMap.put("userName", pt.getUserName());
            qryPtMap.put("wechat_id", pt.getWechat_id());
            qryPtMap.put("tenantId", tenantId);
            // 微信id更新接口
            if (!StringUtils.isBlank(pt.getWechat_id())) {
                patientDao.updateWechatId(qryPtMap);
                // 增加入历史记录
                Map<String, Object> userHisMap = new HashMap<String, Object>();
                userHisMap.put("userId", userId);
                userHisMap.put("updateTime", updateTime);
                userHisMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
                userHisMap.put("updateAccept", updateAccept);
                userHisMap.put("tenantId", tenantId);
                patientDao.savePatientHisInfo(userHisMap);
            }
            logger.warn("该患者[" + pt.getUserName() + "]已经建档，建档时间==[" + pt.getCreateTime() + "]！");
        }

        // 入操作流水记录表 ia_operation_record

        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", pt.getUserName());
        paramRecord.put("userId", userId);
        paramRecord.put("queueId", queueId);
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);

        paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_7);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_PATIENT);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAcceptid);
        // paramRecord.put("tenantId", tenantId);
        String remark = (String) servParamMap.get("opNote");
        if (StringUtils.isBlank(remark)) {
            remark = "患者" + pt.getUserName() + "通过二维码扫码进行建档操作";
        }
        paramRecord.put("remark", remark);
        paramRecord.put("opType", opType);

        // 校验患者是否已经加入过该队列
        HashMap<String, Object> qryPqsMap = new HashMap<String, Object>();
        qryPqsMap.put("userId", userId);
        qryPqsMap.put("queueId", queueId);

        List<String> statulist = new ArrayList<String>();// 查询出暂停和正常 两个状态
        // ,如果查到暂停状态 则提示去恢复
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_SUSPEND);
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT); // 待审核状态
        // 提示去审批

        qryPqsMap.put("status", statulist);

        List<PatientQueueScheme> pqsList = patientQueueSchemeDao.selectByUserId(qryPqsMap);
        if (null != pqsList && 0 != pqsList.size()) {
            logger.error("患者[" + pt.getUserName() + "]已经加入[" + fq.getQueueName() + "]，请不要重复加入！");
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_ALREADY_EXIST,
                    "患者[" + pt.getUserName() + "]已经加入[" + fq.getQueueName() + "]，请不要重复加入！"));
        }

        // 查询方案版本
        String schemeId = fq.getSchemeId();
        String VersionId = "";
        if (!StringUtils.isBlank(schemeId)) {
            VersionId = registerQuery(schemeId);
        }
        // 入患者队列信息表 pt_queuescheme_info
        String schemeVersionId = VersionId;
        String ptQueueSchemeId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTSCHEMEID);
        String cardStatus = (String) servParamMap.get("card_status");
        String cardType = (String) servParamMap.get("card_type");
        String cardNo = (String) servParamMap.get("card_no");

        PatientQueueScheme pts = new PatientQueueScheme();
        pts.setId(ptQueueSchemeId);
        pts.setAuthorId(authorId);
        pts.setCreateTime(updateTime);
        pts.setUpdateTime(updateTime);
        pts.setQueueId(queueId);
        pts.setSchemeId(schemeId);
        pts.setSchemeVersionid(schemeVersionId);
        pts.setUserId(pt.getId());
        pts.setUserStatus(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        pts.setTotalNum(0);
        pts.setUpdateAccept(updateAccept);
        pts.setUpdateAuthor(authorId);
        pts.setFinishNum(1);// 建档任务默认完成
        pts.setCardNo(cardNo);
        pts.setCardStatus(cardStatus);
        pts.setCardType(cardType);
        pts.setTenantId(tenantId);
        pts.setConfirmFlag(Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CONFIRM_INIT);// 待审核

        // 更新队列当前人数+1 fu_queue_info
        FollowQueue fqueueVo = new FollowQueue();
        fqueueVo.setCurrNum(1);
        fqueueVo.setId(queueId);
        fqueueVo.setUpdateTime(updateTime);
        queueDao.updateQueue(fqueueVo);

        // 该队列有对应方案，则需要处理任务相关信息，否则不需要处理
        String taskId_0 = "";// 建档任务id
        if (null != fq.getSchemeId() && !"".equals(fq.getSchemeId())) {
            logger.warn("begin deal task---");
            // 查询当前队列对应方案任务
            HashMap<String, Object> taskQueryParam = new HashMap<String, Object>();
            taskQueryParam.put("schemeVersionid", schemeVersionId);
            taskQueryParam.put("seqNo", Constants.TASK_SEQ_FOR_INIT);
            List<FollowTask> taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
            if (null == taskList || 0 == taskList.size()) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASK_NOT_EXIST, "当前方案对应任务列表为空！"));
            }
            taskQueryParam.remove("seqNo");

            // 实例化方案下任务信息给具体患者
            List<PatientTask> ptTaskList = new ArrayList<PatientTask>();
            List<PatientTaskContent> ptTaskContentList = new ArrayList<PatientTaskContent>();
            // List<String> contentIdList = new ArrayList<String>();
            List<String> taskIdList = new ArrayList<String>();
            FollowTask ft = new FollowTask();
            // int tk = 0;
            int iPrenDay = pt.getPregnancyDay();
            String birthDay = pt.getBirthday();
            String currDay = DateUtil.getCurrDate();
            Map<String, Object> executeMapIn = new HashMap<String, Object>();
            executeMapIn.put("currDay", currDay);
            executeMapIn.put("prenDay", iPrenDay);
            executeMapIn.put("birthDay", birthDay);
            executeMapIn.put("ageDay", ToolUtils.getBirthAgeDay(birthDay));
            // 出院日期，暂无，先写上
            executeMapIn.put("outHospitalDay", servParamMap.get("outHospitalDay"));
            int suffWinDay = 0;// 后窗口期
            int iWinDay = 0;// 前窗口期
            String endTime = "";
            String nextTaskId = "";
            String currTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
            int iseq = 0;
            int lostNum = 0;// 失访任务数
            while (true) {
                ft = taskList.get(0);
                int iTaskSeq = ft.getSeqNo();
                int iCycleDay = ft.getCycleDay();

                // pt_task_info
                if (StringUtils.isEmpty(ft.getNextTaskId())) {
                    nextTaskId = "";
                } else {
                    nextTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
                }
                PatientTask ptk = new PatientTask();
                String ptk_id = currTaskId;
                taskIdList.add(ptk_id);
                ptk.setId(ptk_id);
                ptk.setNextTaskId(nextTaskId);
                currTaskId = nextTaskId;

                // 触发方式
                String executeType = ft.getExecuteType();
                executeMapIn.put("executeType", executeType);
                executeMapIn.put("taskSeq", iTaskSeq);
                executeMapIn.put("cycleDay", iCycleDay);
                executeMapIn.put("executeDay", ft.getExecuteDay());
                executeMapIn.put("inputContData", servParamMap.get("inputContData"));
                String executeTime = ToolUtils.getExecuteTime(executeMapIn);
                iWinDay = ft.getWindowDay();
                suffWinDay = ft.getSuffixWindowDay();
                endTime = DateUtil.calcDay(executeTime, "+", suffWinDay);

                if (Constants.TASK_SEQ_FOR_INIT == iTaskSeq) {
                    taskId_0 = ptk_id;
                    iWinDay = 0;// 建档任务无窗口期
                    suffWinDay = 0;
                    // 建档任务默认完成
                    ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_FINISH);
                    ptk.setUpdateAuname(authorName);
                    ptk.setUpdateAuthor(authorId);
                } else if (endTime.compareTo(currDay) < 0) {
                    // 已过期
                    ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_EXPIRED);
                    lostNum++;
                    // 入失访记录表
                    PtLostRd prdVo = new PtLostRd();
                    prdVo.setAuthorId(authorId);
                    prdVo.setCreateTime(updateTime);
                    prdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_LOST_ID));
                    prdVo.setLostDate(DateUtil.getCurrDate());
                    prdVo.setPtSchemeid(ptQueueSchemeId);
                    prdVo.setQueueId(queueId);
                    prdVo.setReasonId("");
                    prdVo.setTaskId(ptk_id);
                    prdVo.setTaskName(ft.getTaskName());
                    prdVo.setUpdateAccept(updateAccept);
                    prdVo.setUpdateTime(updateTime);
                    prdVo.setUserId(userId);
                    patientTaskDao.savePatientLostInfo(prdVo);
                } else {
                    // 未开始
                    ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_INIT);
                }

                ptk.setAuthorId(authorId);
                ptk.setExecuteTime(executeTime);
                ptk.setBeginTime(DateUtil.calcDay(executeTime, "-", iWinDay));
                ptk.setEndTime(endTime);
                ptk.setCreateTime(updateTime);
                ptk.setExecuteDay(ft.getExecuteDay());
                ptk.setExecuteType(executeType);
                ptk.setInformFlag(ft.getInformFlag());
                ptk.setPtSchemeid(ptQueueSchemeId);
                ptk.setSeqNo(iseq);
                ptk.setTaskIntro(ft.getTaskIntro());
                ptk.setTaskName(ft.getTaskName());
                ptk.setUpdateTime(updateTime);
                ptk.setUserId(pt.getId());
                ptk.setWarnDay(ft.getWarnDay());
                ptk.setWindowDay(iWinDay);
                ptk.setQueueId(queueId);
                ptk.setUpdateAccept(updateAccept);
                if (!StringUtils.isBlank(ft.getTaskType())) {
                    ptk.setTaskType(ft.getTaskType());// 方案中计划型任务
                } else {
                    ptk.setTaskType(Constants.TASK_TYPE_SCHEME_SCHEDULE);// 方案中计划型任务
                }
                ptk.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_INIT);// 初始化审核状态
                ptTaskList.add(ptk);

                // 查询当前任务对应的任务内容
                HashMap<String, Object> taskContentParam = new HashMap<String, Object>();
                taskContentParam.put("taskId", ft.getId());
                taskContentParam.put("schemeVersionid", schemeVersionId);
                List<FollowTaskContent> taskContList = followTaskContDao.selectByTaskId(taskContentParam);
                if (null == taskContList || 0 == taskContList.size()) {
                    continue;
                }

                FollowTaskContent ftc = new FollowTaskContent();
                int tc = 0;
                for (; tc < taskContList.size(); tc++) {
                    ftc = taskContList.get(tc);

                    // 获取内容模板
                    Map<String, Object> templMap = new HashMap<String, Object>();
                    templMap.put("id", ftc.getTemplId());
                    List<ContentTempl> ctList = contentTemplDao.selectTemplById(templMap);
                    if (null == ctList || 0 == ctList.size()) {
                        throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST,
                                "查询任务内容模板版本记录为空！");
                    }
                    ContentTempl conVo = ctList.get(0);

                    // 获取内容模板版本
                    HashMap<String, Object> contVerMap = new HashMap<String, Object>();
                    contVerMap.put("templId", ftc.getTemplId());
                    contVerMap.put("templVersion", ftc.getTemplVersion());
                    List<ContentTemplVersion> ctvList = contentTemplDao.selectContentDataNoTextByTempl(contVerMap);
                    if (null == ctvList || 0 == ctvList.size()) {
                        throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLVERSION_NOT_EXIST,
                                "查询任务内容模板版本记录为空！");
                    }
                    ContentTemplVersion ctv = ctvList.get(0);

                    // pt_taskcontent_info
                    String ptkc_id = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTID);
                    // contentIdList.add(ptkc_id);

                    PatientTaskContent ptc = new PatientTaskContent();
                    ptc.setCreateTime(updateTime);
                    ptc.setUpdateTime(updateTime);
                    ptc.setId(ptkc_id);
                    ptc.setTaskId(ptk_id);
                    ptc.setTemplVersionid(ctv.getId());
                    ptc.setUpdateAccept(updateAccept);
                    ptc.setTemplType(conVo.getTemplType());
                    ptc.setUserId(userId);
                    ptc.setPtSchemeid(ptQueueSchemeId);
                    ptc.setSeqNo(conVo.getSeqNo());

                    ptTaskContentList.add(ptc);
                }
                iseq++;
                if (StringUtils.isEmpty(ft.getNextTaskId())) {
                    break;
                }
                taskQueryParam.put("taskId", ft.getNextTaskId());
                taskList = followTaskDao.selectFollowTaskByScheVerAndId(taskQueryParam);
                if (CollectionUtils.isEmpty(taskList)) {
                    break;
                }
            }
            pts.setTotalNum(ptTaskList.size());
            pts.setLostNum(lostNum);

            // 批量插入，提高效率
            patientTaskDao.savePatientTaskBatch(ptTaskList);
            if (ptTaskContentList.size() > 0) {
                patientTaskConDao.savePatientTaskContentBatch(ptTaskContentList);
            }

            // 记录历史轨迹
            HashMap<String, Object> taskHisParam = new HashMap<String, Object>();
            taskHisParam.put("updateAccept", updateAccept);
            taskHisParam.put("updateType", Constants.UPDATE_TYPE_INSERT);
            taskHisParam.put("ptSchemeid", ptQueueSchemeId);
            taskHisParam.put("updateTime", updateTime);
            patientTaskDao.savePatientTaskHisByPtSchemeid(taskHisParam);

            // 解析建档任务内容（问卷）
            if (null == quesMap || 0 == quesMap.size()) {
                logger.warn("无建档问卷问题--答案记录");
            } else {
                List<PatientContentData> ptcInList = new ArrayList<PatientContentData>();
                Iterator<String> iter = quesMap.keySet().iterator();
                while (iter.hasNext()) {
                    PatientContentData pcdVo = new PatientContentData();
                    String queskey = iter.next();
                    String quesvalue = (String) quesMap.get(queskey);

                    pcdVo.setContentId("");
                    pcdVo.setCreateTime(updateTime);
                    pcdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTDATAID));
                    pcdVo.setQuestionAnswer(quesvalue);
                    pcdVo.setQuestionId(queskey);
                    pcdVo.setTaskId(taskId_0);
                    pcdVo.setUpdateAccept(updateAccept);
                    pcdVo.setUpdateTime(updateTime);
                    pcdVo.setUpdateType(Constants.UPDATE_TYPE_INSERT);
                    pcdVo.setUserId(userId);
                    pcdVo.setPtSchemeid(ptQueueSchemeId);
                    if (Constants.OP_TYPE_DOOR.equals(opType)) {
                        pcdVo.setTemplType(Constants.QUESTIONNAIRE_TYPE_0);
                    } else {
                        // 非门诊问卷，后续补充
                        pcdVo.setTemplType("");
                    }
                    pcdVo.setQueueId(queueId);
                    pcdVo.setTenantId(tenantId);
                    pcdVo.setSourceTypeCreate(sourceType);
                    pcdVo.setSourceTypeUpdate(sourceType);
                    ptcInList.add(pcdVo);
                }
                // 批量插入
                patientTaskConDao.savePatientTaskContentDataBatch(ptcInList);
                patientTaskConDao.savePatientTaskContentDataHisBatch(ptcInList);
            }
        }

        Map<String, Object> insertPtQueueMap = new HashMap<String, Object>();
        insertPtQueueMap.put("id", pts.getId());
        insertPtQueueMap.put("updateTime", pts.getUpdateTime());
        insertPtQueueMap.put("updateAuthor", pts.getUpdateAuthor());
        insertPtQueueMap.put("updateAccept", pts.getUpdateAccept());
        insertPtQueueMap.put("updateType", Constants.UPDATE_TYPE_INSERT);
        patientQueueSchemeDao.savePatientQueueSchemeInfo(pts);
        patientQueueSchemeDao.insertPatientQueueSchemeHis(insertPtQueueMap);

        // 若有建档任务，则将建档任务id入操作记录表
        if (!StringUtils.isEmpty(taskId_0)) {
            paramRecord.put("taskId", taskId_0);
        }
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        if (1 == redisFlag) {
            // redis记录今日新增患者
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.select(Constants.REDIS_DB_INDEX_PATIENT);

                ptQueueRedis.patientAddforQueue(queueId, jedis);
                // ptQueueRedis.patientAddforTenant(tenantId, jedis); //根据科室id
                // 查找租户ID
                if (!Constants.OP_TYPE_SELF.equals(pt.getSourceType())) {
                    // ptQueueRedis.ptDoorAddforAuthor(authorId, jedis);
                }
            } catch (JedisConnectionException jex) {
                logger.error("redis连接异常..." + jex.getMessage());
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
            } finally {
                if (null != jedis) {
                    try {
                        jedis.close();
                        logger.warn("close redis connection...");
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_CLOSE_FAILED,
                                "Redis缓存关闭失败!"));
                    }
                }
            }
        }

        // 实例化模板
        Map<String, Object> paramPtContent = new HashMap<String, Object>();
        paramPtContent.put("ptSchemeId", ptQueueSchemeId);
        paramPtContent.put("ptTaskType", Constants.TASK_TYPE_NONSCHEME_REALTIME);
        paramPtContent.put("userId", userId);
        paramPtContent.put("queueId", queueId);
        paramPtContent.put("userId", userId);
        AppPatientAotuService.addPtcontents(paramPtContent);

        Map<String, Object> mapPatient = new HashMap<String, Object>();
        mapPatient.put("userId", userId);
        mapPatient.put("ptSchemeId", ptQueueSchemeId);
        mapPatient.put("patient", pt);
        mapPatient.put("queueName", fq.getQueueName());// 队列名称
        return mapPatient;
    }

    public String registerQuery(String schemeId) throws Exception {
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("id", schemeId);
        List<FollowScheme> fsList = followSchemeDao.selectById(qrySchemeMap);
        if (null == fsList || 0 == fsList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "方案不存在，处理失败!"));
        }
        FollowScheme fshVo = fsList.get(0);
        Map<String, Object> qrySchemeVerMap = new HashMap<String, Object>();
        qrySchemeVerMap.put("schemeId", schemeId);
        qrySchemeVerMap.put("schemeVersion", fshVo.getNewVersion());
        List<FollowSchemeVersion> fsvList = followSchemeDao.selectBySchemeIdAndVersion(qrySchemeVerMap);
        if (null == fsvList || 0 == fsvList.size()) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEMEVERSION_NOT_EXIST, "方案版本记录不存在!"));
        }
        FollowSchemeVersion fsvVo = fsvList.get(0);

        return fsvVo.getId();

    }

    // 患者数据样本采集标志位更新接口实现
    @Transactional
    public void updatePatientSampleData(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);

        String authorName = (String) argMap.get("authorName");
        String updateTime = (String) argMap.get("updateTime");
        String authorId = (String) argMap.get("authorId");
        String updateAccept = (String) argMap.get("updateAccept");
        String tenantId = (String) argMap.get("tenantId");
        String opCode = (String) argMap.get("opCode");
        String ptSchemeId = (String) argMap.get("ptSchemeId");
        String userId = (String) argMap.get("userId");
        String queueId = (String) argMap.get("queueId");
        String sampleFlag = (String) argMap.get("sampleFlag");
        String sampleType = (String) argMap.get("sampleType");
        String sampleValue = (String) argMap.get("sampleValue");
        String sampleCode = (String) argMap.get("sampleCode");

        // 判断是修改第几次样本状态
        String extendValue1 = "";
        String extendValue2 = "";
        String extendValue3 = "";
        if ("1".equals(sampleValue)) {
            extendValue1 = sampleFlag;
        } else if ("2".equals(sampleValue)) {
            extendValue2 = sampleFlag;
        } else if ("3".equals(sampleValue)) {
            extendValue3 = sampleFlag;
        }

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        Map<String, Object> ptInMap = new HashMap<String, Object>();
        ptInMap.put("userId", userId);
        ptInMap.put("tenantId", tenantId);
        Patient ptOut = patientDao.selectById(ptInMap);
        if (null == ptOut || "".equals(ptOut.getId())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
        }
        paramRecord.put("userName", ptOut.getUserName());
        paramRecord.put("userId", userId);
        paramRecord.put("queueId", queueId);
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        paramRecord.put("type", Constants.DOCTOR_ACTIVE_BUSI_TYPE_10);
        paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", argMap.get("opNote"));
        paramRecord.put("opType", argMap.get("opType"));
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        // 先查询，判断是插入还是更新
        Map<String, Object> extIn = new HashMap<String, Object>();
        extIn.put("userId", userId);
        extIn.put("patientSchemeId", ptSchemeId);
        extIn.put("paramName", sampleType);
        extIn.put("paramType", sampleCode);
        List<PtQueueExtend> ptQueueExtList = ptQueueExtendDao.listPtQueueExtend(extIn);
        if (CollectionUtils.isEmpty(ptQueueExtList)) {
            // 插入
            PtQueueExtend ptqeVo = new PtQueueExtend();
            ptqeVo.setAuthorId(authorId);
            ptqeVo.setCreateTime(updateTime);
            ptqeVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_QUEUEEXTEND_ID));
            ptqeVo.setExtendValue1(extendValue1);
            ptqeVo.setExtendValue2(extendValue2);
            ptqeVo.setExtendValue3(extendValue3);
            ptqeVo.setParamName(sampleType);
            ptqeVo.setParamType(sampleCode);
            ptqeVo.setParamValue("");
            ptqeVo.setPtSchemeid(ptSchemeId);
            ptqeVo.setQueueId(queueId);
            ptqeVo.setRemark("");
            ptqeVo.setTenantId(tenantId);
            ptqeVo.setUpdateTime(updateTime);
            ptqeVo.setUserId(userId);
            ptQueueExtendDao.savePtQueueExtend(ptqeVo);
        } else {
            // 更新
            Map<String, Object> extUpIn = new HashMap<String, Object>();
            extUpIn.put("updateTime", updateTime);
            extUpIn.put("extendValue1", extendValue1);
            extUpIn.put("extendValue2", extendValue2);
            extUpIn.put("extendValue3", extendValue3);
            extUpIn.put("userId", userId);
            extUpIn.put("patientSchemeId", ptSchemeId);
            extUpIn.put("paramType", sampleCode);
            extUpIn.put("paramName", sampleType);
            ptQueueExtendDao.updatePtQueueExtend(extUpIn);
        }

        return;
    }

    // 患者异常记录接口实现
    @Transactional
    public void savePtExcpInfo(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);
        PtExcpRd excpVo = new PtExcpRd();

        String updateTime = (String) argMap.get("updateTime");
        if (StringUtils.isEmpty(updateTime)) {
            updateTime = DateUtil.getTimeString(DateUtil.getSysDateA());
        }

        String errMsg = (String) argMap.get("errMsg");
        if (!StringUtils.isEmpty(errMsg)) {
            if (errMsg.length() >= Constants.STRING_LEN_512) {
                // 截取前面512个字符
                errMsg = errMsg.substring(0, 512);
            }
        }

        excpVo.setCreateTime(updateTime);
        excpVo.setExcpStatus("");
        excpVo.setExcpType(Constants.PT_EXCP_TYPE_APP);
        excpVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_EXCP_RD_ID));
        excpVo.setOpCode((String) argMap.get("opCode"));
        excpVo.setOpType((String) argMap.get("opType"));
        excpVo.setPtSchemeid((String) argMap.get("ptSchemeId"));
        excpVo.setQueueId((String) argMap.get("queueId"));
        excpVo.setTaskId((String) argMap.get("taskId"));
        excpVo.setTenantId((String) argMap.get("tenantId"));
        excpVo.setUpdateAccept((String) argMap.get("updateAccept"));
        excpVo.setUpdateAuthor((String) argMap.get("authorId"));
        excpVo.setUpdateTime(updateTime);
        excpVo.setUserId((String) argMap.get("userId"));
        excpVo.setErrMsg(errMsg);
        excpVo.setRuleId((String) argMap.get("ruleId"));
        ptExcpDao.savePtExcpRd(excpVo);

        return;
    }

    @Override
    public Map<String, Object> getPatientInfoByUserId(Map<String, Object> paramMap) throws Exception {
        String patientId = (String) paramMap.get("patientId");
        String tenantId = (String) paramMap.get("tenantId");

        Map<String, Object> ptMap = new HashMap<String, Object>();
        ptMap.put("userId", patientId);
        ptMap.put("tenantId", tenantId);
        Patient pt = patientDao.selectById(ptMap);
        if (null == pt || StringUtils.isEmpty(pt.getId())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
        }

        Map<String, Object> outRet = new HashMap<String, Object>();
        if ("0".equals((String) paramMap.get("showFlag"))) {
            List<PatientContentData> lists = patientTaskConDao.listCntDataByUserIdAndAcceptPrivate(ptMap);
            if (!CollectionUtils.isEmpty(lists)) {
                for (int j = 0; j < lists.size(); j++) {
                    if (Constants.QUESTION_ID_FOR_WEIGHT.equals(lists.get(j).getQuestionId())) {
                        outRet.put("weight", lists.get(j).getQuestionAnswer());
                    } else if (Constants.QUESTION_ID_FOR_DELIVERY.equals(lists.get(j).getQuestionId())) {
                        outRet.put("delivery", lists.get(j).getQuestionAnswer());
                    } else if (Constants.QUESTION_ID_FOR_OUTPATIENT.equals(lists.get(j).getQuestionId())) {
                        outRet.put("outpatient", lists.get(j).getQuestionAnswer());
                    } else if (Constants.QUESTION_ID_FOR_CARD1.equals(lists.get(j).getQuestionId())) {
                        outRet.put("socialCard", lists.get(j).getQuestionAnswer());
                    } else if (Constants.QUESTION_ID_FOR_CARD2.equals(lists.get(j).getQuestionId())) {
                        outRet.put("cardNo", lists.get(j).getQuestionAnswer());
                    } else if (Constants.QUESTION_ID_FOR_JIUZHENG.equals(lists.get(j).getQuestionId())) {
                        outRet.put("correctAge", lists.get(j).getQuestionAnswer());
                    }
                }
            }
        }

        /* 2017-10-07 add by wuyz */
        if (!StringUtils.isBlank((String) paramMap.get("examinationPaperName"))) {
            // 需要返回评估信息
            ptMap.put("type", (String) paramMap.get("examinationPaperName"));
            PtEvaluationResult pr = followEvaluationDao.selectEvaluationResultBytime(ptMap);
            outRet.put("Evaluation", pr);
        }

        outRet.put("PatientInfo", pt);
        outRet.put("pregnancyWeekStr", ToolUtils.getPregnancyStr(pt.getPregnancyDay()));
        outRet.put("ageMonDayStr", ToolUtils.getAgeMonDayByBirthday(pt.getBirthday()));

        return outRet;
    }

    // 生物样本采集处理（安医大需求）
    public Map<String, Object> dealSampleInfo(Map<String, Object> mapIn) throws Exception {
        String userId = (String) mapIn.get("userId");
        String ptSchemeId = (String) mapIn.get("ptSchemeId");
        String updateTime = (String) mapIn.get("updateTime");
        String authorId = (String) mapIn.get("authorId");
        String tenantId = (String) mapIn.get("tenantId");
        String queueId = (String) mapIn.get("queueId");
        String sampleType = "";
        String sampleCode = "";
        String extendValue1 = "";
        String extendValue2 = "";
        String extendValue3 = "";

        List<Map<String, Object>> sampleList = ToolUtils.typeCast(mapIn.get("sampleList"));
        int ssize = sampleList.size();
        int sp = 0;
        Map<String, Object> sampleMap = new HashMap<String, Object>();
        for (sp = 0; sp < ssize; sp++) {
            sampleMap = sampleList.get(sp);
            sampleType = (String) sampleMap.get("sampleType");
            sampleCode = (String) sampleMap.get("sampleCode");
            extendValue1 = (String) sampleMap.get("sampleValue1");
            extendValue2 = (String) sampleMap.get("sampleValue2");
            extendValue3 = (String) sampleMap.get("sampleValue3");

            // 先查询，判断是插入还是更新
            Map<String, Object> extIn = new HashMap<String, Object>();
            extIn.put("userId", userId);
            extIn.put("patientSchemeId", ptSchemeId);
            extIn.put("paramName", sampleType);
            extIn.put("paramType", sampleCode);
            List<PtQueueExtend> ptQueueExtList = ptQueueExtendDao.listPtQueueExtend(extIn);
            if (CollectionUtils.isEmpty(ptQueueExtList)) {
                // 插入
                PtQueueExtend ptqeVo = new PtQueueExtend();
                ptqeVo.setAuthorId(authorId);
                ptqeVo.setCreateTime(updateTime);
                ptqeVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_QUEUEEXTEND_ID));
                ptqeVo.setExtendValue1(extendValue1);
                ptqeVo.setExtendValue2(extendValue2);
                ptqeVo.setExtendValue3(extendValue3);
                ptqeVo.setParamName(sampleType);
                ptqeVo.setParamType(sampleCode);
                ptqeVo.setParamValue("");
                ptqeVo.setPtSchemeid(ptSchemeId);
                ptqeVo.setQueueId(queueId);
                ptqeVo.setRemark("");
                ptqeVo.setTenantId(tenantId);
                ptqeVo.setUpdateTime(updateTime);
                ptqeVo.setUserId(userId);
                ptQueueExtendDao.savePtQueueExtend(ptqeVo);
            } else {
                // 更新
                Map<String, Object> extUpIn = new HashMap<String, Object>();
                extUpIn.put("updateTime", updateTime);
                extUpIn.put("extendValue1", extendValue1);
                extUpIn.put("extendValue2", extendValue2);
                extUpIn.put("extendValue3", extendValue3);
                extUpIn.put("userId", userId);
                extUpIn.put("patientSchemeId", ptSchemeId);
                extUpIn.put("paramType", sampleCode);
                extUpIn.put("paramName", sampleType);
                ptQueueExtendDao.updatePtQueueExtend(extUpIn);
            }
        }

        return null;
    }

    // 生物样本采集状态查询（安医大需求）
    public List<Map<String, Object>> listSampleInfo(Map<String, Object> mapIn) throws Exception {
        String userId = (String) mapIn.get("userId");
        String ptSchemeId = (String) mapIn.get("ptSchemeId");
        String tenantId = (String) mapIn.get("tenantId");

        Map<String, Object> staticMapIn = new HashMap<String, Object>();
        staticMapIn.put("type", Constants.PT_BIOLOGY_SAMPLE_TYPE);
        staticMapIn.put("paramCode", Constants.PT_BIO_SAMPLE_PARAM_CODE_AYD);
        staticMapIn.put("tenantId", tenantId);
        List<Map<String, Object>> staticList = confCacheDao.selectBsStaticParamByTenant(staticMapIn);
        List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
        if (!CollectionUtils.isEmpty(staticList)) {
            int ssize = staticList.size();
            int sp = 0;
            Map<String, Object> staticMapOut = new HashMap<String, Object>();
            Map<String, Object> extIn = new HashMap<String, Object>();
            String paramValue = "";
            for (sp = 0; sp < ssize; sp++) {
                Map<String, Object> outMap = new HashMap<String, Object>();
                extIn.clear();
                staticMapOut = staticList.get(sp);
                paramValue = (String) staticMapOut.get("PARAM_VALUE");
                outMap.put("sampleType", paramValue);

                extIn.put("userId", userId);
                extIn.put("patientSchemeId", ptSchemeId);
                extIn.put("paramName", paramValue);
                extIn.put("paramType", Constants.PT_BIO_SAMPLE_PARAM_CODE_AYD);
                List<PtQueueExtend> ptQueueExtList = ptQueueExtendDao.listPtQueueExtend(extIn);
                if (CollectionUtils.isEmpty(ptQueueExtList)) {
                    outMap.put("sampleValue1", "");
                    outMap.put("sampleValue2", "");
                    outMap.put("sampleValue3", "");
                } else {
                    PtQueueExtend ptQueueExtVo = ptQueueExtList.get(0);
                    outMap.put("sampleValue1", ptQueueExtVo.getExtendValue1());
                    outMap.put("sampleValue2", ptQueueExtVo.getExtendValue2());
                    outMap.put("sampleValue3", ptQueueExtVo.getExtendValue3());
                }
                outList.add(outMap);
            }
        }

        return outList;
    }

    /**
     * Edit by jiangq on 2022年01月18日
     * 近12个月用户数量
     *
     * @param tenantId
     * @return
     */
    public List<Map<String, Object>> calcRecentUsers(String tenantId) {
        return patientDao.calcRecentUsers(tenantId);
    }

    @Override
    public Map<String, Object> patientListPage(PatientPageReqDTO reqDTO, HttpServletRequest request) throws Exception {
        //患者列表
        Map<String, Object> sessionMap = ToolUtils.getSessionInfo(request);
        HashMap<String, Object> paramMap = Dict.parse(reqDTO);
        Integer currentPage = reqDTO.getCurrentPage() == null ? 1 : reqDTO.getCurrentPage();
        Integer pageSize = reqDTO.getPageSize() == null ? 10 : reqDTO.getPageSize();
        paramMap.put("tenantId", sessionMap.get("tenantId"));
        PageHelper.startPage(currentPage, pageSize);
        List<PatientListBO> list = patientDao.selectList(paramMap);
        if (ObjectUtil.isNotEmpty(list)) {
            String authorId = (String) sessionMap.get("authorId");
            List<String> queueIds = followQueueAuthorityDAO.getDuiLieByAuthorId(authorId);
            list = list.stream().filter(item -> {
                if (queueIds.contains(item.getQueueId())) {
                    return true;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());
        }
        PageInfo<PatientListBO> page = new PageInfo<>(list);
        HashMap<String, Object> responseMap = MapUtil.newHashMap();
        responseMap.put("data", list);
        responseMap.put("count", page.getTotal());
        return responseMap;
    }

    @Override
    @Transactional
    public synchronized void updatePatientStatus(PatientUpdateStatusReqDTO reqDTO, HttpServletRequest request) throws Exception {
        //更新患者状态
        Map<String, Object> sessionMap = ToolUtils.getSessionInfo(request);
        HashMap<String, Object> paramMap = MapUtil.newHashMap();
        paramMap.put("tenantId", sessionMap.get("tenantId"));
        paramMap.put("userId", reqDTO.getUserId());
        //特殊处理
        HashMap<String, Object> param2Map = MapUtil.newHashMap();
        param2Map.put("userStatus", "0");
        List<PatientQueueScheme> patientQueueSchemes = patientQueueSchemeDao.selectPatientByCondition(param2Map);
        if (CollUtil.isNotEmpty(patientQueueSchemes)) {
            List<String> userIds = patientQueueSchemes.stream().map(PatientQueueScheme::getUserId).collect(Collectors.toList());
            paramMap.put("notIds", userIds);
        }
        List<PatientListBO> list = patientDao.selectList(paramMap);
        if (CollUtil.isNotEmpty(list)) {
            PatientListBO patientListBO = list.get(0);
            boolean flag = false;
            PtUserInfoExt ptUserInfoExt = ptUserInfoExtDAO.selectOneByUserId(reqDTO.getUserId());
            if (ptUserInfoExt == null) {
                flag = true;
                ptUserInfoExt = new PtUserInfoExt();
                ptUserInfoExt.setId(IdUtil.getSnowflake(1, 1).nextIdStr());
                ptUserInfoExt.setUserId(patientListBO.getId());
            }
            ptUserInfoExt.setInHospitalTime(patientListBO.getInpatientDate());
            ptUserInfoExt.setOutHospitalTime(reqDTO.getOutHospitalTime());
            ptUserInfoExt.setOutHospitalRemark(reqDTO.getOutHospitalRemark());
            ptUserInfoExt.setTransferHospitalTime(reqDTO.getTransferHospitalTime());
            ptUserInfoExt.setTransferHospitalRemark(reqDTO.getTransferHospitalRemark());
            //只给来源是外院且操作出院的人发送邮件
            if (PatientHospitalStatusEnum.CY.getName().equals(reqDTO.getStatus())
                    && HospitalTypeEnum.HOSPITAL_OUTER.getName().equals(patientListBO.getSourceHospitalType())) {
                List<FdHospitalEmailConfig> fdHospitalEmailConfigs = fdHospitalEmailConfigDAO.selectAll();
                for (FdHospitalEmailConfig fdHospitalEmailConfig : fdHospitalEmailConfigs) {
                    //发送邮件(启动状态)
                    if (fdHospitalEmailConfig.getHospitalName().equals(patientListBO.getHospitalName())
                            && fdHospitalEmailConfig.getStatus() == 1) {
                        Map map = MapUtil.newHashMap();
                        map.put("日期", cn.hutool.core.date.DateUtil.format(reqDTO.getOutHospitalTime(), "yyyy-MM-dd"));
                        map.put("住院号", patientListBO.getInPatientNo());
                        map.put("房间床号", patientListBO.getHospitalBedNo());
                        map.put("姓名", patientListBO.getName());
                        map.put("性别", patientListBO.getGender().equals("N") ? "男" : "女");
                        //去掉开头的结束
                        String[] pregnancyWeekArr = StrUtil.subBetweenAll(patientListBO.getPregnancyWeek(), "[", "]");
                        if (null != pregnancyWeekArr && 0 != pregnancyWeekArr.length) {
                            String[] pregnancyWeek = StrUtil.split(pregnancyWeekArr[0], ",");
                            map.put("孕周", StrUtil.nullToDefault(pregnancyWeek[0] + "-", "") + StrUtil.nullToDefault(pregnancyWeek[1], ""));
                        } else {
                            map.put("孕周", "");
                        }
                        map.put("转运体重", patientListBO.getTransferWeight());
                        map.put("产院", patientListBO.getHospitalName());
                        map.put("转入诊断", patientListBO.getTransferRemark());
                        map.put("转出诊断", ptUserInfoExt.getOutHospitalRemark());
                        map.put("转出日期", cn.hutool.core.date.DateUtil.format(ptUserInfoExt.getOutHospitalTime(), "yyyy-MM-dd"));
                        map.put("转归", patientListBO.getHospitalWard());
                        String content = StrUtil.format(emailHtml, map);
                        List<String> emails = StrUtil.splitTrim(fdHospitalEmailConfig.getHospitalEmail(), ",");
                        if (CollUtil.isNotEmpty(emails)) {
                            handleSendEmail(emails, "出院提醒", content);
                        }
                        ptUserInfoExt.setEmailMessage(JSONUtil.toJsonStr(map));
                        ptUserInfoExt.setEmailReceiver(fdHospitalEmailConfig.getHospitalEmail());
                    }
                }
            }
            ptUserInfoExt.setRemark("变更患者状态");
            if (flag) {
                ptUserInfoExt.setCreater(sessionMap.get("loginId").toString());
                ptUserInfoExt.setCreateTime(cn.hutool.core.date.DateUtil.date());
                ptUserInfoExt.setUpdateTime(cn.hutool.core.date.DateUtil.date());
                ptUserInfoExtDAO.insert(ptUserInfoExt);
            } else {
                ptUserInfoExt.setUpdateTime(cn.hutool.core.date.DateUtil.date());
                ptUserInfoExtDAO.updateByPrimaryKeySelective(ptUserInfoExt);
            }
            //更新建档的信息
            //修改患者在院状态
            HashMap<String, Object> updateParam = MapUtil.newHashMap();
            updateParam.put("questionAnswer", reqDTO.getStatus());
            updateParam.put("tenantId", patientListBO.getTenantId());
            updateParam.put("userId", reqDTO.getUserId());
            updateParam.put("questionId", "zcejd_sfzy");
            patientTaskContentDAO.updateAnswerByTenantIdAndUserIdAndQuestionId(updateParam);
        }
    }

    @Override
    public List<String> hospitalList(HttpServletRequest request) {
        List<FdHospitalEmailConfig> fdHospitalEmailConfigs = fdHospitalEmailConfigDAO.selectAll();
        return fdHospitalEmailConfigs.stream().map(FdHospitalEmailConfig::getHospitalName).collect(Collectors.toList());
    }

    //根据patientId获取脑卒中量表的测量记录
    @Override
    public Map<String, Object> getNirnAssessData(String patientId) {
        String baseNirnUrl = PropertiesUtils.getProperty("baseNirnUrl");
        String getNirnAssessDataUrl = baseNirnUrl+"/web/scale/getNirnAssessData"+"?patientId="+patientId;
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<Map> entity = restTemplate.getForEntity(getNirnAssessDataUrl, Map.class);
        Map<String, Object> resMap = new HashMap<>();
        if ((int)entity.getBody().get("code") == 0){
            resMap.put("riskFactors",entity.getBody().get("riskFactors"));
            resMap.put("guide",entity.getBody().get("guide"));
            return resMap;
        }
        return resMap;
    }

    //根据患者id查询患者最近一次随访内容
    @Override
    public List<PatientContentData> queryPatientRecentlyFollowRecord(Map<String, Object> map) {
        List<PatientContentData> patientContentDataList = patientDao.queryPatientRecentlyFollowRecord(map);
        return patientContentDataList;
    }

    @Override
    public void updateAccessStatus(String userId, String accessStatus) {
        patientDao.updateAccessStatus(userId,accessStatus);
    }


    /**
     * 发送邮件
     *
     * @param receiveEmail 接手邮箱的人
     * @param subject      标题
     * @param content      提醒内容
     */
    private void handleSendEmail(List<String> receiveEmail, String subject, String content) {
        MailAccount account = new MailAccount();
        //邮件服务器的SMTP地址，可选，默认为smtp.<发件人邮箱后缀>
        account.setHost("smtp.163.com");
        //邮件服务器的SMTP端口，可选，默认25
        account.setPort(465);
        //发件人（必须正确，否则发送失败）
        account.setFrom(" 复旦大学附属儿科医院儿科 <pediatricFD@163.com>");
        //用户名，默认为发件人邮箱前缀
        account.setUser("pediatricFD");
        //密码（注意，某些邮箱需要为SMTP服务单独设置授权码，详情查看相关帮助）
        account.setPass("RRNXNJPETQJGLSGZ");
        //使用SSL安全连接
        account.setSslEnable(true);
        //TODO 需要改为html：true
        MailUtil.send(account, receiveEmail, subject, content, false);
    }

    /**
     * Edit by jiangq on 2022年12月14日
     * 线上随访相关
     * 患者任务内容列表查询接口实现
     *
     * @param paramMap
     * @return
     * @throws Exception
     */
    public HashMap<String, Object> qryOnlinePatientContentList(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        HashMap<String, Object> retOutMap = new HashMap<String, Object>();
        String taskId = (String) argMap.get("taskId");
        String queueId = (String) argMap.get("queueId");
        List<PatientTask> ptVoList = patientTaskDao.selectById(argMap);
        if (null == ptVoList || 0 == ptVoList.size()) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASK_NOT_EXIST, "该患者当前任务不存在！");
        }
        PatientTask ptTaskVo = ptVoList.get(0);
        if (Constants.TASK_SEQ_FOR_INIT == ptTaskVo.getSeqNo()) {
            // 建档任务需要将基本信息返回
            Map<String, Object> userMap = new HashMap<String, Object>();
            userMap.put("userId", ptTaskVo.getUserId());

            Patient ptVo = patientDao.selectById(userMap);
            if (null == ptVo) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
            }
            retOutMap.put("patientInfo", ptVo);

            // 患者扩展信息
            Map<String, Object> outExtMap = new HashMap<String, Object>();
            Map<String, Object> ptExtMap = new HashMap<String, Object>();
            ptExtMap.put("userId", ptVo.getId());
            List<PtUserextendInfo> ptextList = ptExtendDao.selectPtExtendInfo(ptExtMap);
            if (null != ptextList && 0 != ptextList.size()) {
                int iextNum = ptextList.size();
                int kk = 0;
                for (kk = 0; kk < iextNum; kk++) {
                    PtUserextendInfo pextVo = ptextList.get(kk);
                    outExtMap.put(pextVo.getParamName(), pextVo.getParamValue());
                }
            }
            retOutMap.put("extendInfo", outExtMap);
        }

        List<Object> conDataList = new ArrayList<Object>();
        List<Object> contentIdList = new ArrayList<Object>();
        List<PatientTaskContent> ptcList = patientTaskConDao.selectContentByTaskId(argMap);
        ptcList = ptcList.stream().filter(item -> item.getTemplType().equals(Constants.QUESTIONNAIRE_TYPE_9)).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(ptcList)) {
            // questiones
            int ipt = 0;
            int isize = ptcList.size();
            Map<String, Object> templMap = new HashMap<String, Object>();
            Map<String, Object> equalMap = new HashMap<String, Object>();
            // 找出模板内容相同的问卷
            for (ipt = 0; ipt < isize; ipt++) {
                PatientTaskContent ptaskc = ptcList.get(ipt);
                String templType = ptaskc.getTemplType();
                String templVersionId = ptaskc.getTemplVersionid();
                if (Constants.QUESTIONNAIRE_TYPE_0.equals(templType)) {
                    templMap.put("id", templVersionId);
                    List<ContentTemplVersion> ctvList = contentTemplDao.selectContentTemplNoTextById(templMap);
                    if (null == ctvList || 0 == ctvList.size()) {
                        continue;
                    }
                    String equalId = ctvList.get(0).getEqualId();
                    if (!StringUtils.isEmpty(equalId)) {
                        equalMap.put(equalId, templVersionId);
                    }
                }
            }
            logger.warn("equalMap==" + equalMap.toString());

            // 剔除相同内容的非门诊问卷
            boolean eraseFlag = false;
            Map<String, Object> dataOut = new HashMap<String, Object>();
            Map<String, Object> contVerMap = new HashMap<String, Object>();
            for (ipt = 0; ipt < isize; ipt++) {
                PatientTaskContent ptaskc = ptcList.get(ipt);
                Map<String, Object> ptcInMap = new HashMap<String, Object>();
                String templType = ptaskc.getTemplType();
                String templVersionId = ptaskc.getTemplVersionid();
                if (!Constants.QUESTIONNAIRE_TYPE_0.equals(templType)) {
                    if (null != equalMap.get(templVersionId)) {
                        // 该问卷与门诊问卷内容相同，需要剔除
                        logger.warn("erase templVersionId==" + templVersionId);
                        eraseFlag = true;
                        continue;
                    }
                }
                ptcInMap.put("templType", templType);
                ptcInMap.put("contentId", ptaskc.getId());
                contentIdList.add(ptcInMap);

                // 获取内容模板
                contVerMap.clear();
                contVerMap.put("templVersionId", templVersionId);
                dataOut = getContTemplData(contVerMap);
                if (null != dataOut.get("contData")) {
                    conDataList.add(dataOut.get("contData"));
                }
            }
            retOutMap.put("questiones", conDataList);

            // values
            HashMap<String, Object> questionMap = new HashMap<String, Object>();
            List<PatientContentData> ptTaskConList;
            if (!eraseFlag) {
                // 没有重复问卷，优先查门诊答案，没有门诊答案，则查询所有答案
                Map<String, Object> valMapIn = new HashMap<String, Object>();
                valMapIn.put("taskId", taskId);
                valMapIn.put("contDataTemplType", Constants.QUESTIONNAIRE_TYPE_0);
                ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                if (!CollectionUtils.isEmpty(ptTaskConList)) {
                    int k = 0;
                    for (; k < ptTaskConList.size(); k++) {
                        PatientContentData pcdVo = ptTaskConList.get(k);
                        questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                    }
                } else {
                    valMapIn.put("contDataTemplType", null);
                    ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                    if (!CollectionUtils.isEmpty(ptTaskConList)) {
                        int k = 0;
                        for (; k < ptTaskConList.size(); k++) {
                            PatientContentData pcdVo = ptTaskConList.get(k);
                            questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                        }
                    }
                }
            } else {
                // 有重复的问卷，则需要考虑两种情况：
                // 1、门诊问卷已有答案，则使用自己的答案
                // 2、门诊问卷没有答案，则使用关联问卷的答案
                Map<String, Object> valMapIn = new HashMap<String, Object>();
                valMapIn.put("taskId", taskId);
                valMapIn.put("contDataTemplType", Constants.QUESTIONNAIRE_TYPE_0);
                ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                if (!CollectionUtils.isEmpty(ptTaskConList)) {
                    int k = 0;
                    for (; k < ptTaskConList.size(); k++) {
                        PatientContentData pcdVo = ptTaskConList.get(k);
                        questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                    }
                } else {
                    valMapIn.clear();
                    valMapIn.put("taskId", taskId);
                    ptTaskConList = patientTaskConDao.selectContentDataByTaskId(valMapIn);
                    if (!CollectionUtils.isEmpty(ptTaskConList)) {
                        int k = 0;
                        for (; k < ptTaskConList.size(); k++) {
                            PatientContentData pcdVo = ptTaskConList.get(k);
                            questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
                        }
                    }
                }
            }
            retOutMap.put("values", questionMap);
            retOutMap.put("PtContentdataInfo", ptTaskConList);
        }

        // task
        Map<String, Object> taskMap = new HashMap<String, Object>();
        taskMap.put("ptTaskId", taskId);
        taskMap.put("ptContentIds", contentIdList);
        taskMap.put("ptTaskName", ptTaskVo.getTaskName());
        taskMap.put("taskNote", ptTaskVo.getTaskNote());
        taskMap.put("updateAuname", ptTaskVo.getUpdateAuname());
        taskMap.put("seqNo", ptTaskVo.getSeqNo());
        taskMap.put("taskStatus", ptTaskVo.getTaskStatus());// 任务状态
        taskMap.put("taskDate", ptTaskVo.getExecuteTime());// 任务计划执行日期
        // 随访日期和完成时间不是同一天时，已随访日期为准
        String finishTime = ptTaskVo.getFinishTime();
        String finishDate = ptTaskVo.getFinishDate();

        if (finishDate == null) {
            if (!StringUtils.isEmpty(ptTaskVo.getTemporaryTask()) && ptTaskVo.getTemporaryTask().equals("1")) {
                //临时随访。
                taskMap.put("finishDate", ptTaskVo.getExecuteTime());
            } else {
                taskMap.put("finishDate", "");
            }
        } else {
            taskMap.put("finishDate", finishDate);
        }

        String finishTimeSplit = "";
        if (StringUtils.isBlank(finishTime)) {
            finishTime = finishDate;
        } else {
            finishTimeSplit = DateUtil.getTimeStampDay(finishTime);
            if (StringUtils.isNotBlank(finishDate) && !finishDate.equals(finishTimeSplit)) {
                finishTime = finishDate;
            }
        }
        if (finishTime == null) {
            //taskMap.put("finishTime", "");
        } else {
            taskMap.put("finishTime", finishTime);
        }

        Map<String, String> nextDateMap = new HashMap<String, String>();
        List<String> nextDateList = new ArrayList<String>();
        String nextDate = ptTaskVo.getNextDate();
        if (!StringUtils.isEmpty(nextDate)) {
            // 将已填写过的下次随访日期放在第一选项
            String nextDateTime = "";
            if (-1 != nextDate.indexOf(Constants.COLON_SPLIT_STR)) {
                String[] nextDateArr = nextDate.split(Constants.COLON_SPLIT_STR);
                nextDateTime = nextDateArr[0];
            } else {
                nextDateTime = nextDate;
            }
            nextDateList.add(nextDateTime);
            nextDateMap.put(nextDateTime, "1");
            taskMap.put("nextDateTime", nextDateTime);
        }

        taskMap.put("nextDate", nextDateList);

        retOutMap.put("task", taskMap);

        // opr_info
        HashMap<String, Object> oprInfoMap = new HashMap<String, Object>();
        oprInfoMap.put("patientId", ptTaskVo.getUserId());
        oprInfoMap.put("ptSchemeId", ptTaskVo.getPtSchemeid());
        oprInfoMap.put("followQueueId", queueId);
        retOutMap.put("oprInfo", oprInfoMap);
        retOutMap.put("PtTaskcontentInfo", ptcList);

        return retOutMap;
    }

}
